Introducing 

Prezi AI.

Your new presentation assistant.

Refine, enhance, and tailor your content, source relevant images, and edit visuals quicker than ever before.

Loading…
Transcript

#ifndef __GENERATED_php_test_fws_h1c89c124__

#define __GENERATED_php_test_fws_h1c89c124__

namespace HPHP {

///////////////////////////////////////////////////////////////////////////////

// 1. Static Strings

extern StaticString s_ss3994978b;

// 2. Static Arrays

// 3. Static Variants

///////////////////////////////////////////////////////////////////////////////

}

#endif // __GENERATED_php_test_fws_h1c89c124__

#include <runtime/base/hphp.h>

#include <sys/literal_strings_remap.h>

#include <sys/scalar_arrays_remap.h>

#include <sys/scalar_integers_remap.h>

#include <sys/global_variables.h>

#include <sys/cpputil.h>

#include <php/test.fws.h>

#include <php/test.h>

// Dependencies

#include <runtime/ext/ext.h>

namespace hphp_impl_starter {}

namespace HPHP {

///////////////////////////////////////////////////////////////////////////////

/* preface starts */

extern CallInfo ci_;

/* preface finishes */

Variant pm_php$test_php(bool incOnce, LVariableTable* variables, Globals *globals) {

PSEUDOMAIN_INJECTION(run_init::test.php, pm_php$test_php);

LVariableTable *gVariables ATTRIBUTE_UNUSED = (LVariableTable *)g;

echo(NAMSTR(s_ss3994978b, "hello world"));

return true;

}

namespace hphp_impl_splitter {}

///////////////////////////////////////////////////////////////////////////////

}

v_a = s_sa00000000;

v_a.append((NAMVAR(s_svif01bca90, 0LL)));

v_a.set(NAMSTR(s_ssfde820e1, "er"), (NAMVAR(s_svse59fa416, "x")), true);

v_a.set(NAMSTR(s_ssf04a85df, "acx"), (s_sva905e1b1b), true);

v_a.append((NAMVAR(s_svi90d5f98c, 2LL)));

LINE(8,(x_var_dump(1, v_a)));

return true;

PHP>$a = array();

C++>v_a = s_sa00000000;

PHP>$a[] = 0;

C++>v_a.append((NAMVAR(s_svif01bca90, 0LL)));

PHP>$a['er'] = 'x';

C++>v_a.set(NAMSTR(s_ssfde820e1, "er"), (NAMVAR(s_svse59fa416, "x")), true);

PHP>$a['acx'] = array('oge','hoge');

C++>v_a.set(NAMSTR(s_ssf04a85df, "acx"), (s_sva905e1b1b), true); //あれ?

PHP>$a[] = 2;

C++>v_a.append((NAMVAR(s_svi90d5f98c, 2LL)));

v_a = NAMSTR(s_sse6f62137, "hello");

{

LINE(3,0);

const Variant &tmp0((x_strstr(toString(v_a), NAMVAR(s_svs546f1cb9, "he"))));

v_b.assignVal(tmp0);

}

LINE(5,(x_var_dump(2, v_a, Array(array_createvi(1, toVPOD(v_b))))));

return true;

<?php

$func = function($param1)

{

return $param1 + 1;

};

$a = $func(10);

var_dump($a);

/* preface starts */

extern CallInfo ci_;

extern CallInfo ci_08511066943069959013_1;

/* preface finishes */

/* SRC: test10.php line 3 */

Numeric f_08511066943069959013_1(void *extra, CVarRef v_param1) {

FUNCTION_INJECTION(08511066943069959013_1);

INTERCEPT_INJECTION("08511066943069959013_1", array_createvi(1, toVPOD(v_param1)), r);

return (v_param1 + 1LL);

}

namespace hphp_impl_splitter {}

Variant ifa_08511066943069959013_1(void *extra, int count, INVOKE_FEW_ARGS_IMPL_ARGS) {

if (UNLIKELY(count < 1)) throw_missing_arguments("08511066943069959013_1", count+1);

CVarRef arg0(UNLIKELY(count <= 0) ? null_variant : a0);

return (f_08511066943069959013_1(extra, arg0));

}

Variant i_08511066943069959013_1(void *extra, CArrRef params) {

return invoke_func_few_handler(extra, params, &ifa_08511066943069959013_1);

}

CallInfo ci_08511066943069959013_1((void*)&i_08511066943069959013_1, (void*)&ifa_08511066943069959013_1, 1, 0, 0x0000000000000000LL);

Variant pm_php$test10_php(bool incOnce, LVariableTable* variables, Globals *globals) {

PSEUDOMAIN_INJECTION(run_init::test10.php, pm_php$test10_php);

LVariableTable *gVariables ATTRIBUTE_UNUSED = (LVariableTable *)g;

Variant &v_func ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_sse63d8c2d, "func")) : g->GV(func);

Variant &v_a ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ss27b9150a, "a")) : g->GV(a);

{

LINE(6,0);

p_Closure tmp0((p_Closure(NEWOBJ(c_Closure)(&ci_08511066943069959013_1, NULL))));

v_func = tmp0;

}

{

const CallInfo *cit0;

void *vt0;

get_call_info_or_fail(cit0, vt0, v_func);

LINE(8,0);

Variant tmp1(((cit0->getFunc1Args())(vt0, 1, 10LL)));

v_a.assignVal(tmp1);

}

LINE(9,(x_var_dump(1, v_a)));

return true;

}

B キャプチャしている変数の割り当て

v_a = 10LL;

if (equal(v_a, 10LL)) {

{

echo(NAMSTR(s_ssa4ae39ed, "10"));

}

}

else {

{

echo(NAMSTR(s_ss2dcad959, "else!"));

}

}

return true;

<?php

$a = 10;

if ($a === 10 ){

echo "10";

}

else

{

echo "else!";

}

v_a = 10LL;

if (same(v_a, 10LL)) {

{

echo(NAMSTR(s_ssa4ae39ed, "10"));

}

}

else {

{

echo(NAMSTR(s_ss2dcad959, "else!"));

}

}

return true;

<?php

$for_sum = 0;

for($a = 0 ; $a <= 10 ; $a ++)

{

$for_sum += $a;

}

$while_sum = 0;

$a = 10;

while($a)

{

$while_sum += $a;

$a --;

}

v_for_sum = 0LL;

{

LOOP_COUNTER(1);

for (v_a = 0LL; (not_more(v_a, 10LL)); v_a++) {

LOOP_COUNTER_CHECK(1);

{

v_for_sum += v_a;

}

}

}

v_while_sum = 0LL;

v_a = 10LL;

LOOP_COUNTER(2);

{

while (toBoolean(v_a)) {

LOOP_COUNTER_CHECK(2);

{

v_while_sum += v_a;

v_a--;

}

}

}

{

LOOP_COUNTER(1);

for (v_a = 0LL; (less(v_a, 10LL)); v_a++) {

LOOP_COUNTER_CHECK(1);

{

{

LOOP_COUNTER(2);

for (v_b = 0LL; (less(v_b, 10LL)); v_b++) {

LOOP_COUNTER_CHECK(2);

{

if (equal(v_b, 2LL)) {

{

break;

}

}

if (equal(v_a, 5LL)) {

{

goto break1;

}

}

}

}

}

}

}

break1:;

}

<?php

$a = 10;

switch($a)

{

case 10:

$b = "10";

break;

case "2":

$b = "2string!";

break;

}

v_a = 10LL;

{

Variant switch2 = (v_a);

if (equal(switch2, (10LL))) goto case_2_0;

if (equal(switch2, (NAMSTR(s_ssebb8aab9, "2")))) goto case_2_1;

goto break1;

}

case_2_0:

{

v_b = NAMSTR(s_ssa4ae39ed, "10");

goto break1;

}

case_2_1:

{

v_b = NAMSTR(s_ss5bb3adb6, "2string!");

goto break1;

}

break1:;

<?php

function myfunc($a)

{

throw new Exception("hoe-");

}

try

{

myfunc(1);

}

catch(Exception $e)

{

echo "catch!";

}

Variant pm_php$test24_tpl(bool incOnce, LVariableTable* variables, Globals *globals) {

PSEUDOMAIN_INJECTION(run_init::test24.tpl, pm_php$test24_tpl);

LVariableTable *gVariables ATTRIBUTE_UNUSED = (LVariableTable *)g;

Variant &v_a ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ss27b9150a, "a")) : g->GV(a);

echo(NAMSTR(s_ss18b6f89c, "hello "));

echo(toString(v_a));

echo(NAMSTR(s_ss66d2232c, "\n"));

return true;

}

FORWARD_DECLARE_CLASS(myclass);

extern const ObjectStaticCallbacks cw_myclass;

class c_myclass : public ObjectData {

public:

// Properties

// Class Map

DECLARE_CLASS_NO_SWEEP(myclass, myclass, ObjectData)

c_myclass(const ObjectStaticCallbacks *cb = &cw_myclass) : ObjectData(cb, false) {}

public: Numeric t_pubfunc(CVarRef v_a);

DECLARE_METHOD_INVOKE_HELPERS(pubfunc);

};

ObjectData *coo_myclass() NEVER_INLINE;

えんいー\e

3/7

6/7

7/7

5/7

4/7

2/7

1/7

未来の部屋

Regexp Assemble for PHP

世界一わかりやすいポインタ

萌え萌えCSS

音声認識の

誤認識フィルタとしての機械学習

なのは完売

新潟アクセス修飾子

自己紹介

とある関数の電脳戦

(バトルプログラミング)

世界で2番目に

hiphop php

が生成する

C++のコードを

読んでみよう。

perlの魔術的ライブラリ

Regexp AssembleをPHPに移植。

正規表現を機械的に作成する。

ポインタを

超わかりやすく説明

音声認識を利用して

家電制御を制御する

未来の部屋

自己紹介

こんちにはー

jQueryを

萌え化する

プロセスの乗っ取りを防ぐ

アンチフックの話

そして、攻性防壁の構築。

一部アセンブラ

by rti

public

protected

private

そして niigata

名前: rti

仕事: 起業準備中という名の引きこもり??

肩書き: シーランド公国伯爵

特技: イオナズンが使えます。

最近のトレンド: 音声認識

http://d.hatena.ne.jp/rti7743/

http://rtilabs.net/

音声認識の誤認識フィルタにSVMを応用するお話です。

https://twitter.com/#!/super_rti

http://prezi.com/9t_u8vkfbukc/

http://d.hatena.ne.jp/rti7743/20111220/1324389840

http://prezi.com/jwn5gq36td7y/presentation/

http://rtilabs.net/files/2011_11_02/

http://prezi.com/2r6wmrriyeqb/niigata/

http://d.hatena.ne.jp/rti7743/20120104/1325668680

http://rtilabs.net/files/2010_12_24/moemoe_css/

処理の流れ

hiphop phpって何?

インストール方法

パフォーマンス

ベンチマーク

Regexp Assemble for PHP

どうやって早くしているんだろう?

からの発表

A

PHPで作ったプログラム

すべてに一致する正規表現を自動生成する。

処理系 速度

PHP 5.3.3 15.260s

PHP 5.4RC4 11.556s

hiphop php 5.022s

B

Scientific Linux 6.1 (64bit)でテスト

が作った、

C

hiphop php

が生成する

C++のコードを

読んでみよう。

hiphop phpとは?

パフォーマンス

通常のwebアプリだと DBなどがネックになる。

PHPだけのロジックで速度を測る。

今回は、自作の regexp assemble for PHP を使う。

C++に変換!!(hiphopのしごと)

インストール方法

D

facebook

centos5系でも入るよ。

パッケージで苦労するけど。

32bit系でも入らなくはないけど、、、

とても苦労するが。

HipHop for PHP。

HipHopにより私たちはページによっては、

Webサーバー上で約50パーセントのCPU使用量を削減できました。

CPUの使用量の少なさは、サーバー台数の削減につながり、

それはより少ないオーバーヘッドを意味します。

今回は hiphop phpがどうやって、

PHPを C++ に変換しているのかについて

みていきたいと思います。

E

<?php

require_once("Regexp_Assemble.php");

for($i = 0 ; $i < 10000 ; ++$i ) {

$reg = new Regexp_Assemble();

$reg->add('神岸あかり');

$reg->add('赤座あかり');

$reg->add('黒座あかり');

$str = $reg->as_string();

$reg = new Regexp_Assemble();

$reg->add('スティーブ・ジョブズ');

$reg->add('スティーブ・ウォズアニック');

$str = $reg->as_string();

$reg = new Regexp_Assemble();

$reg->add('お兄ちゃま');

$reg->add('あにぃ');

$reg->add('お兄様');

$reg->add('おにいたま');

$reg->add('兄上様');

$reg->add('にいさま');

$reg->add('アニキ');

$reg->add('兄くん');

$reg->add('兄君さま');

$reg->add('兄チャマ');

$reg->add('兄や');

$str = $reg->as_string();

}

#追加リポジトリ

rpm -Uvh http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm

rpm -Uvh http://ftp.iij.ad.jp/pub/linux/fedora/epel/6/x86_64/epel-release-6-5.noarch.rpm

#アップデートと開発ツールのインストール

yum -y update

yum -y groupinstall "Development Tools"

#依存パッケージで yum で入るものを入れる.

yum -y --enablerepo=rpmforge,epel install git cmake libssh2 gd gd-devel mysql-server mysql-devel php php-cli php-common php-mbstring php-pear python-devel icu libicu-devel oniguruma oniguruma-devel flex memcached libmemcached bison re2c mysql mysql-devel libxml2 libxml2-devel libmcrypt libmcrypt-devel php-mcrypt openssl binutils binutils-devel libcap libcap-devel gd zlib bzip2 bzip2-libs bzip2-devel pcre pcre-devel expat expat-devel gd gd-devel openldap openldap-devel readline readline-devel libc-client libc-client-devel ncurses ncurses-devel pam pam-devel libmcrypt libmcrypt-devel wget tbb tbb-devel

# libmemcache

# OS標準が古いのでアップデートする

#

cd /usr/local/src/

wget http://download.tangent.org/libmemcached-0.43.tar.gz

tar -xvf libmemcached-0.43.tar.gz

cd libmemcached-0.43

./configure --prefix=/usr

make

make install

# boost

# OS標準が古いので新しいやつを /usr/に上書きで。。。

#

cd /usr/local/src/

wget 'http://sourceforge.net/projects/boost/files/boost/1.48.0/boost_1_48_0.tar.gz/download'

tar -xvf boost_1_48_0.tar.gz

cd boost_1_48_0

./bootstrap.sh

./b2 install --prefix=/usr

# download hiphop

# 先にダウンロードしないと patchが手に入らない

#

cd /usr/local/src/

git clone git://github.com/facebook/hiphop-php.git

# install libcurl

# うちでは /usr/に上書きした

#

cd /usr/local/src/

wget http://curl.haxx.se/download/curl-7.20.0.tar.bz2

tar -xvf curl-7.20.0.tar.bz2

cp hiphop-php/src/third_party/libcurl.fb-changes.diff curl-7.20.0/

cd curl-7.20.0

sed -i 's/curl-old\///g' libcurl.fb-changes.diff

sed -i 's/curl-new\///g' libcurl.fb-changes.diff

patch -p0 < libcurl.fb-changes.diff

./configure --with-ssl --with-zlib --with-libidn --enable-sspi --enable-ldap --enable-ldaps --prefix=/usr

make

make install

# install libevent

# うちでは /usr/に上書きした

#

cd /usr/local/src/

wget http://monkey.org/~provos/libevent-1.4.13-stable.tar.gz

tar -xvf libevent-1.4.13-stable.tar.gz

cp hiphop-php/src/third_party/libevent-1.4.13.fb-changes.diff libevent-1.4.13-stable/

cd libevent-1.4.13-stable

sed -i 's/libevent-1.4.13-stable\///g' libevent-1.4.13.fb-changes.diff

sed -i 's/libevent-1.4.13-stable-fb\///g' libevent-1.4.13.fb-changes.diff

patch -p0 < libevent-1.4.13.fb-changes.diff

./configure --prefix=/usr

make

make install

ldconfig

# install hiphop

cd /usr/local/src/

cd hiphop-php/

export HPHP_HOME="/usr/local/src/hiphop-php"

export HPHP_LIB="/usr/local/src/hiphop-php/bin"

cmake -DCMAKE_PREFIX_PATH=/usr .

make

make install

#export で環境変数を定義している。ログアウトすると消えるので注意。

#毎回有効にしたい人は、 ~/.bashrc にでも。

#コピペ用

export HPHP_HOME="/usr/local/src/hiphop-php"

export HPHP_LIB="/usr/local/src/hiphop-php/bin"

F

gccとかでコンパイル。最適化。

C++

<?php

require_once("Regexp_Assemble.php");

$reg = new Regexp_Assemble();

$reg->add('お兄ちゃん');

$reg->add('お兄ちゃま');

$reg->add('あにぃ');

$reg->add('お兄様');

$reg->add('おにいたま');

$reg->add('兄上様');

$reg->add('にいさま');

$reg->add('アニキ');

$reg->add('兄くん');

$reg->add('兄君さま');

$reg->add('兄チャマ');

$reg->add('兄や');

//(?:お(?:兄(?:ちゃ[まん]|様)|にいたま)|兄(?:チャマ|君さま|くん|上様|や)|にいさま|あにぃ|アニキ)

echo $reg->as_string();

トランスレーター

PHP

正規表現を自動生成してくれるツール。

perlのライブラリからの勝手移植。

正味2000行~3000行

G

http://developers.facebook.com/news.php?blog=1&story=358 の翻訳 http://blog.candycane.jp/archives/275

実行が超早くなる。

hiphop PHPは、

PHP5.3の3倍、PHP5.4の 2倍以上の速さ

by rti

H

ネイティヴコードで実行

(ここまで前ふり)

結果→

I

変換されたソースを見る。

hiphop PHP独自の文字列型

って何?

hello world のコードをもっと単純化して

書くと、こんな感じになります。

echo(s_ss3994978b);

C++に変換は一瞬でも

コンパイルには結構時間が掛かる。

echo(NAMSTR(s_ss3994978b, "hello world"));

変換とコンパイル

元のPHPのコード test.php

C++に変換

hello world

<?php

echo "hello world";

class StaticString : public String {

//略

}

一度だけ必要

extern StaticString s_ss3994978b;

#define NAMVAR(nam, str) (nam)

test.php

export HPHP_HOME="/usr/local/src/hiphop-php"

export HPHP_LIB="/usr/local/src/hiphop-php/bin"

hphp_test/php/test.h

hphp_test/php/test.fws.hで定義

php/test.fws.h

hphp_test/php/test.cpp

runtime/base/macros.h で定義

echo(NAMSTR(s_ss3994978b, "hello world"));

StaticString s_ss3994978b("hello world");

echo(s_ss3994978b);

runtime/base/type_string.h で定義

hello world

C++のだめなところに

コンパイルがとても遅いところがあるが、

hiphopが作ったコードのコンパイルも遅い。

hello worldで 1分程度の時間がかかる。

hiphop PHPが作るコードは、

PHP実行環境も内包しているためとてもでかいのだ。

Stringクラス構造

#ifndef __GENERATED_php_test_h70588221__

#define __GENERATED_php_test_h70588221__

// Declarations

namespace HPHP {

///////////////////////////////////////////////////////////////////////////////

// Includes and Functions

Variant pm_php$test_php(bool incOnce, LVariableTable* variables, Globals *globals);

// Constants

///////////////////////////////////////////////////////////////////////////////

}

#endif // __GENERATED_php_test_h70588221__

running hphp...

creating temporary directory /tmp/hphp_vlzsBB ...

parsing inputs...

parsing inputs took 0'00" (5 ms) wall time

pre-optimizing...

pre-optimizing took 0'00" (0 ms) wall time

inferring types...

inferring types took 0'00" (0 ms) wall time

post-optimizing...

post-optimizing took 0'00" (0 ms) wall time

creating CPP files...

creating CPP files took 0'00" (48 ms) wall time

compiling and linking CPP files...

compiling and linking CPP files took 0'56" (56326 ms) wall time

running executable /tmp/hphp_vlzsBB/program --file test.php...

hello worldall files saved in /tmp/hphp_vlzsBB ...

running hphp took 0'56" (56802 ms) wall time

StaticString s_ss3994978b("hello world");

hphp test.php --keep-tempdir=1 --log=3

echo(s_ss3994978b);

<?php

echo "hello world";

でsys\literal_strings_0.no.cppで定義

遅い!

class StaticString : public String

class String : public SmartPtr<StringData>

class StringData

変換するPHP名

"hello world"という文字は、

人間が見て分かるためのものだった

StaticStringって何?

テンポラリのソースコードがみたいので

テンポラリ

PHPとC++を対訳

Variant型の宣言

Variant型

C++で variant作る時の2つの方法

PHPには、 $$a のように、

変数の中に入っている

文字列が表している

変数名にアクセス

することができます。

こっちぽい

A 変数の型宣言

フラグ + union

Variant型とは?

VBやMS-COM回りで遊んでいた人にお馴染みの、

なんでも代入できる型。

<?php

$a = "b";

$b = 20;

$c = $$a;

var_dump($c);

PSEUDOMAIN_INJECTION(run_init::test13.php, pm_php$test13_php);

LVariableTable *gVariables ATTRIBUTE_UNUSED = (LVariableTable *)g;

Variant &v_a ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ss27b9150a, "a")) : g->GV(a);

Variant &v_b ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ssf8576bd5, "b")) : g->GV(b);

Variant &v_c ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ss5c5509b0, "c")) : g->GV(c);

v_a = NAMSTR(s_ssf8576bd5, "b");

v_b = 20LL;

v_c.assignVal(variables->get(toString(v_a)));

LINE(7,(x_var_dump(1, v_c)));

return true;

変数の文字列呼び出し

class Variant {

public:

//中略

Variant(bool v) : _count(0), m_type(KindOfBoolean) { m_data.num = (v?1:0);}

Variant(int v) : _count(0), m_type(KindOfInt32 ) { m_data.num = v;}

Variant(int64 v) : _count(0), m_type(KindOfInt64 ) { m_data.num = v;}

Variant(uint64 v) : _count(0), m_type(KindOfInt64 ) { m_data.num = v;}

Variant(long v) : _count(0), m_type(KindOfInt64 ) { m_data.num = v;}

Variant(double v) : _count(0), m_type(KindOfDouble ) { m_data.dbl = v;}

//中略

};

<?php

$a = 1;

$b = "hello";

$c = 2;

$c = "str";

$d = array();

$d[] = 10;

$d['ex'] = 20;

$d[] = 30;

var_dump($a,$b,$c,$d);

型をフラグでもっていて、

データ自体は unionに入れる。

クラスが絡むと面倒

変数

B ロジック

Variant pm_php$test8_php(bool incOnce, LVariableTable* variables, Globals *globals) {

PSEUDOMAIN_INJECTION(run_init::test8.php, pm_php$test8_php);

LVariableTable *gVariables ATTRIBUTE_UNUSED = (LVariableTable *)g;

Variant &v_a ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ss27b9150a, "a")) : g->GV(a);

Variant &v_b ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ssf8576bd5, "b")) : g->GV(b);

Variant &v_c ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ss5c5509b0, "c")) : g->GV(c);

Variant &v_d ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ssaa9bf7c4, "d")) : g->GV(d);

v_a = 1LL;

v_b = NAMSTR(s_sse6f62137, "hello");

v_c = 2LL;

v_c = NAMSTR(s_ss8f83bd9c, "str");

v_d = s_sa00000000;

v_d.append((NAMVAR(s_svi542bad8b, 10LL)));

v_d.set(NAMSTR(s_ssd2bea2d3, "ex"), (NAMVAR(s_svid7a79683, 20LL)), true);

v_d.append((NAMVAR(s_svifc87a5f7, 30LL)));

LINE(14,(x_var_dump(4, v_a, Array(array_createvi(3, toVPOD(v_b), toVPOD(v_c), toVPOD(v_d))))));

return true;

}

PHP>$a = 1;

C++>v_a = 1LL;

PHP>$b = "hello";

C++>v_b = NAMSTR(s_sse6f62137, "hello");

PHP>$c = 2;

PHP>$c = "str";

C++>v_c = 2LL;

C++>v_c = NAMSTR(s_ss8f83bd9c, "str");

PHP>$d = array();

PHP>$d[] = 10;

PHP>$d['ex'] = 20;

PHP>$d[] = 30;

C++>v_d = s_sa00000000;

C++>v_d.append((NAMVAR(s_svi542bad8b, 10LL)));

C++>v_d.set(NAMSTR(s_ssd2bea2d3, "ex"), (NAMVAR(s_svid7a79683, 20LL)), true);

C++>v_d.append((NAMVAR(s_svifc87a5f7, 30LL)));

PHP 型が比較的自由

C++ 厳格な型

template + new

runtime/base/type_variant.hで定義

なんでも代入できる!!

自前で参照カウントっぽいものをもっている。

boost::anyとかこっち。

型が綺麗に表現できる。

が、newが細切れに発生

variables はローカル変数を管理している。

ローカル変数の面倒な初期化はこのため。

要略の壁を埋めるには、 Variant という緩衝材が必要。

C++だと boost::anyなどあるが hiphopは自前実装。

対訳

array('oge','hoge');はどこに?

StaticArray型

前回のソースから配列だけ

<?php

$a = array();

$a[] = 0;

$a['er'] = 'x';

$a['acx'] = array('oge','hoge');

$a[] = 2;

var_dump($a);

静的に決定できる配列の最適化

C++>v_d = s_sa00000000;

C++>v_d.append((NAMVAR(s_svi542bad8b, 10LL)));

C++>v_d.set(NAMSTR(s_ssd2bea2d3, "ex"), (NAMVAR(s_svid7a79683, 20LL)), true);

C++>v_d.append((NAMVAR(s_svifc87a5f7, 30LL)));

配列

class StaticArray : public Array {

public:

StaticArray() { }

StaticArray(ArrayData *data) : Array(data) {

m_px->setStatic();

m_px->onSetStatic();

}

~StaticArray() {

m_px = NULL;

}

};

static const char sa_cdata[63] = {

0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,

0x4b, 0xb4, 0x32, 0xb2, 0xaa, 0xce, 0xb4, 0x32, 0xb0, 0x4e,

0xb4, 0x32, 0xb0, 0xaa, 0xae, 0xcd, 0xb4, 0x32, 0x04, 0xb2,

0xa0, 0x42, 0xc5, 0x56, 0xc6, 0x56, 0x4a, 0xf9, 0xe9, 0xa9,

0x4a, 0xd6, 0x20, 0xe1, 0x62, 0x2b, 0x13, 0x2b, 0xa5, 0x0c,

0x30, 0xb7, 0xb6, 0x16, 0x00, 0x63, 0x28, 0xf5, 0x8a, 0x37,

0x00, 0x00, 0x00, };

StaticArray ScalarArrays::sa_[2];

void ScalarArrays::initialize() {

SystemScalarArrays::initialize();

ArrayUtil::InitScalarArrays(sa_, 2, sa_cdata, 63);

ScalarArrays::initializeNamed();

}

gz圧縮

PHP>$d = array();

PHP>$d[] = 10;

PHP>$d['ex'] = 20;

PHP>$d[] = 30;

C++>v_d = s_sa00000000;

C++>v_d.append((NAMVAR(s_svi542bad8b, 10LL)));

C++>v_d.set(NAMSTR(s_ssd2bea2d3, "ex"), (NAMVAR(s_svid7a79683, 20LL)), true);

C++>v_d.append((NAMVAR(s_svifc87a5f7, 30LL)));

gz解凍

extern StaticArray s_sa00000000;

静的に決定できる配列の最適化がある。

静的テーブルは gz 圧縮で効率化

関数の戻り値まとめ

戻り値を返さない

文字列かNULLを返す場合

関数を返す場合

Arrayを返す場合

Array型は、Variantではない

Numeric最適化・・・されません。

p_Closure 型

関数の実体

Numeric型だとおもった?

残念。 Variant型でした。

直接呼ばれているのは、関数の実体が書いてある f_myfunc

備考

場合

myfuncが3つある。

function say($str)

{

echo $str;

}

function myfunc($x)

{

if ($x % 2 == 0)

{

return $x;

}

return NULL;

}

Numeric

Variantのtypedef

数値型

function myfunc($x)

{

return function()

{

return 1;

};

}

function myfunc($x)

{

return array($x);

}

typedef Variant Numeric;

function myfunc($v)

{

return $v + 1;

}

Array f_myfunc(CVarRef v_x) {

FUNCTION_INJECTION(myfunc);

INTERCEPT_INJECTION("myfunc", array_createvi(1, toVPOD(v_x)), r);

return Array(array_createvi(1, toVPOD(v_x)));

}

runtime/base/types.h で定義

String

文字型

ちゃんと戻り値が

void 型になりました

他の関数の戻り値型も見てみよう

p_Closure 型に

なりました。

<?php

function myfunc($v)

{

return $v + 1;

}

$a = myfunc(3);

var_dump($a);

Array

配列

戻り値が Variant になりました。

まーしかたない。

extern CallInfo ci_;

extern CallInfo ci_myfunc;

Numeric f_myfunc(CVarRef v_v) {

FUNCTION_INJECTION(myfunc);

INTERCEPT_INJECTION("myfunc", array_createvi(1, toVPOD(v_v)), r);

return (v_v + 1LL);

}

namespace hphp_impl_splitter {}

Variant ifa_myfunc(void *extra, int count, INVOKE_FEW_ARGS_IMPL_ARGS) {

if (UNLIKELY(count < 1)) throw_missing_arguments("myfunc", count+1);

CVarRef arg0(UNLIKELY(count <= 0) ? null_variant : a0);

return (f_myfunc(arg0));

}

Variant i_myfunc(void *extra, CArrRef params) {

return invoke_func_few_handler(extra, params, &ifa_myfunc);

}

CallInfo ci_myfunc((void*)&i_myfunc, (void*)&ifa_myfunc, 1, 0, 0x0000000000000000LL);

Variant pm_php$test12_php(bool incOnce, LVariableTable* variables, Globals *globals) {

PSEUDOMAIN_INJECTION(run_init::test12.php, pm_php$test12_php);

LVariableTable *gVariables ATTRIBUTE_UNUSED = (LVariableTable *)g;

Variant &v_a ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ss27b9150a, "a")) : g->GV(a);

{

LINE(8,0);

const Numeric &tmp0((f_myfunc(NAMVAR(s_svia6bfbbdd, 3LL))));

v_a.assignVal(tmp0);

}

LINE(9,(x_var_dump(1, v_a)));

return true;

}

関数

{

LINE(8,0);

const Numeric &tmp0((f_myfunc(NAMVAR(s_svia6bfbbdd, 3LL))));

v_a.assignVal(tmp0);

}

↓↓↓f_myfunc を呼び出す↓↓

Numeric f_myfunc(CVarRef v_v) {

FUNCTION_INJECTION(myfunc);

INTERCEPT_INJECTION("myfunc", array_createvi(1, toVPOD(v_v)), r);

return (v_v + 1LL);

}

クロージャーと関数を返す関数との

厳密な意味は違うが、

最近区別が曖昧になってる。

C++11ともそうなんだけど。

関数返していれば、

束縛しようとしまいとクロージャーらしい

p_Closure

関数

Numeric f_myfunc(CVarRef v_v) {

FUNCTION_INJECTION(myfunc);

INTERCEPT_INJECTION("myfunc", array_createvi(1, toVPOD(v_v)), r);

return (v_v + 1LL);

}

int値が Variantを経由するなんてやや残念です。

int値が2^31を超えてしまったときに

float型に変換されるとかの PHP の仕様が

響いているのでしょうか?

class Array : public SmartPtr<ArrayData> {

}

void f_say(CVarRef v_str) {

FUNCTION_INJECTION_NOMEM(say);

INTERCEPT_INJECTION("say", array_createvi(1, toVPOD(v_str)), );

echo(toString(v_str));

}

Variant f_myfunc(CVarRef v_x) {

FUNCTION_INJECTION(myfunc);

INTERCEPT_INJECTION("myfunc", array_createvi(1, toVPOD(v_x)), r);

if (equal(modulo(toInt64(v_x), 2LL), 0LL)) {

{

return v_x;

}

}

return null;

}

p_Closure f_myfunc(CVarRef v_x) {

FUNCTION_INJECTION(myfunc);

INTERCEPT_INJECTION("myfunc", array_createvi(1, toVPOD(v_x)), r);

return LINE(7,(p_Closure(NEWOBJ(c_Closure)(&ci_07358007151305723156_1, NULL))));

}

Array f_myfunc(CVarRef v_x) {

FUNCTION_INJECTION(myfunc);

INTERCEPT_INJECTION("myfunc", array_createvi(1, toVPOD(v_x)), r);

return Array(array_createvi(1, toVPOD(v_x)));

}

別の値と混合

Variant

runtime/base/type_array.hで定義

void

値を返さない

戻り値が Numeric型 になってる。

typedef Variant Numeric;

他は何に使っているのでしょうか?

今はわからないので、置いといて先に進みましょう。

束縛(キャプチャ)

キャプチャはクラスで表現

CallInfo型

無名関数

A classができた

組み込み関数

ディフォルト引数

<?php

$a = "hello";

$b = strstr($a,"he");

var_dump($a,$b);

<?php

$cap = 10;

$func = function($a) use($cap)

{

return $a + $cap + 1;

};

$c = $func(2); //2 + 10 + 1

var_dump($c);

C 関数の情報

束縛(キャプチャ)

FORWARD_DECLARE_CLASS(Closure$07296613028076329051_1);

class c_Closure$07296613028076329051_1 : public c_Closure {

public:

DECLARE_OBJECT_ALLOCATION_NO_SWEEP(c_Closure$07296613028076329051_1)

Variant v_cap;

c_Closure$07296613028076329051_1(const CallInfo *func, void *extra, CVarRef r_cap) : c_Closure(func, extra) {

v_cap.assignVal(r_cap);

}

};

function myfunc($x, $v = 1)

{

return $x + $v + 1;

}

x_strstrがPHPの組み込み関数

無名関数

PHP組み込み関数

extern CallInfo ci_;

extern CallInfo ci_07296613028076329051_1;

FORWARD_DECLARE_CLASS(Closure$07296613028076329051_1);

class c_Closure$07296613028076329051_1 : public c_Closure {

public:

DECLARE_OBJECT_ALLOCATION_NO_SWEEP(c_Closure$07296613028076329051_1)

Variant v_cap;

c_Closure$07296613028076329051_1(const CallInfo *func, void *extra, CVarRef r_cap) : c_Closure(func, extra) {

v_cap.assignVal(r_cap);

}

};

/* preface finishes */

/* SRC: test27.php line 4 */

Numeric f_07296613028076329051_1(void *extra, CVarRef v_a) {

FUNCTION_INJECTION(07296613028076329051_1);

INTERCEPT_INJECTION("07296613028076329051_1", array_createvi(1, toVPOD(v_a)), r);

c_Closure$07296613028076329051_1 *closure ATTRIBUTE_UNUSED = (c_Closure$07296613028076329051_1*)extra;

Variant v_cap;

v_cap.assignVal(closure->v_cap);

return (v_a + (v_cap + 1LL));

}

namespace hphp_impl_splitter {}

Variant ifa_07296613028076329051_1(void *extra, int count, INVOKE_FEW_ARGS_IMPL_ARGS) {

if (UNLIKELY(count < 1)) throw_missing_arguments("07296613028076329051_1", count+1);

CVarRef arg0(UNLIKELY(count <= 0) ? null_variant : a0);

return (f_07296613028076329051_1(extra, arg0));

}

Variant i_07296613028076329051_1(void *extra, CArrRef params) {

return invoke_func_few_handler(extra, params, &ifa_07296613028076329051_1);

}

CallInfo ci_07296613028076329051_1((void*)&i_07296613028076329051_1, (void*)&ifa_07296613028076329051_1, 1, 0, 0x0000000000000000LL);

IMPLEMENT_OBJECT_ALLOCATION_NO_DEFAULT_SWEEP(c_Closure$07296613028076329051_1)

Variant pm_php$test27_php(bool incOnce, LVariableTable* variables, Globals *globals) {

PSEUDOMAIN_INJECTION(run_init::test27.php, pm_php$test27_php);

LVariableTable *gVariables ATTRIBUTE_UNUSED = (LVariableTable *)g;

Variant &v_cap ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ssf0ead937, "cap")) : g->GV(cap);

Variant &v_func ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_sse63d8c2d, "func")) : g->GV(func);

Variant &v_c ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ss5c5509b0, "c")) : g->GV(c);

v_cap = 10LL;

{

LINE(7,0);

p_Closure tmp0((p_Closure$07296613028076329051_1(NEWOBJ(c_Closure$07296613028076329051_1)(&ci_07296613028076329051_1, NULL, v_cap))));

v_func = tmp0;

}

{

const CallInfo *cit0;

void *vt0;

get_call_info_or_fail(cit0, vt0, v_func);

LINE(9,0);

Variant tmp1(((cit0->getFunc1Args())(vt0, 1, 2LL)));

v_c.assignVal(tmp1);

}

LINE(10,(x_var_dump(1, v_c)));

return true;

}

ディフォルト引数

class CallInfo {

public:

~中略~

FuncInvoker getFunc() const { return (FuncInvoker)m_invoker; }

FuncInvokerFewArgs getFuncFewArgs() const {

return (FuncInvokerFewArgs)m_invokerFewArgs;

}

typedef Variant (*FuncInvoker0Args)(

void*, int);

typedef Variant (*FuncInvoker1Args)(

void*, int, CVarRef);

typedef Variant (*FuncInvoker2Args)(

void*, int, CVarRef, CVarRef);

typedef Variant (*FuncInvoker3Args)(

void*, int, CVarRef, CVarRef, CVarRef);

typedef Variant (*FuncInvoker4Args)(

void*, int, CVarRef, CVarRef, CVarRef,

CVarRef);

~中略~

typedef Variant (*FuncInvoker10Args)(

void*, int, CVarRef, CVarRef, CVarRef,

CVarRef, CVarRef, CVarRef, CVarRef, CVarRef, CVarRef, CVarRef);

FuncInvoker0Args getFunc0Args() const {

return (FuncInvoker0Args)m_invokerFewArgs;

}

FuncInvoker1Args getFunc1Args() const {

return (FuncInvoker1Args)m_invokerFewArgs;

}

FuncInvoker2Args getFunc2Args() const {

return (FuncInvoker2Args)m_invokerFewArgs;

}

FuncInvoker3Args getFunc3Args() const {

return (FuncInvoker3Args)m_invokerFewArgs;

}

FuncInvoker4Args getFunc4Args() const {

return (FuncInvoker4Args)m_invokerFewArgs;

}

~中略~

FuncInvoker10Args getFunc10Args() const {

return (FuncInvoker10Args)m_invokerFewArgs;

}

~略~

};

関数の制約

引数の異なる関数のポインタをラップするクラス

C++11のtemplate...があれば・・・・

A 無名関数

B 呼び出し

このクラスに、無名関数のへの関数ポインタを

入れて呼び出しできるようにする。

とても妥当な実装だと思う。

これも、C++11では captureがあるので、

今作ると別の方になりそう。

C 初期化時に cap を渡している。

lambdaの仕様を自前で実装しているので、

回りくどい。

今は、C++11 lambda もあるから

もうちょっといいルーチンが書けるかもしれないが・・・

Numeric f_myfunc(CVarRef v_x,

CVarRef v_v = NAMVAR(s_svib794f8ce, 1LL));

C++の関数のディフォルト引数になる。

include

例外

include

switch 文字列

switch

break

foreach

includeされる方を

見てみる

includeするところを

見てみる。

無限ループ検出器

LOOP_COUNTER と LOOP_COUNTER_CHECK

test24.cpp

test24.fws.h

test24.h

test24.tpl.nophp.cpp

test24.tpl.nophp.fws.h

test24.tpl.nophp.h

forとwhile

<?php

$a = 10;

include("test24.tpl");

test24.cpp

test24.fws.h

test24.h

test24.tpl.nophp.cpp

test24.tpl.nophp.fws.h

test24.tpl.nophp.h

B 例外送信部

<?php

$arr = array(0,1,2,3,4,5,6,7,8,9);

foreach($arr as $key => $val)

{

echo "{$key} => {$val}\n";

}

===比較演算子

test24.cpp

test24.fws.h

test24.h

test24.tpl.nophp.cpp

test24.tpl.nophp.fws.h

test24.tpl.nophp.h

if

<?php

$a = 10;

switch($a)

{

case 10:

$b = "10";

break;

case 2:

$b = "2";

break;

}

v_a = 10LL;

switch ((v_a).hashForIntSwitch(10LL, 0LL)) {

case 10LL:

{

v_b = NAMSTR(s_ssa4ae39ed, "10");

break;

}

case 2LL:

{

v_b = NAMSTR(s_ssebb8aab9, "2");

break;

}

}

<?php

for($a = 0 ; $a < 10 ; $a ++ )

{

for($b = 0 ; $b < 10 ; $b ++)

{

if ($b == 2)

{

break;

}

if ($a == 5)

{

break 2;

}

}

}

例外

switch

break

goto先生

ちっすちっす

--test24.tpl--

hello <?php echo $a ?>

include

void f_myfunc(CVarRef v_a) {

FUNCTION_INJECTION_NOMEM(myfunc);

INTERCEPT_INJECTION("myfunc", array_createvi(1, toVPOD(v_a)), );

throw_exception(LINE(5,(p_Exception(((c_Exception*)coo_Exception())->create(NAMVAR(s_svsd792abf7, "hoe-"))))));

}

//略

CallInfo ci_myfunc((void*)&i_myfunc, (void*)&ifa_myfunc, 1, 0, 0x0000000000000000LL);

Variant pm_php$test17_php(bool incOnce, LVariableTable* variables, Globals *globals) {

PSEUDOMAIN_INJECTION(run_init::test17.php, pm_php$test17_php);

LVariableTable *gVariables ATTRIBUTE_UNUSED = (LVariableTable *)g;

Variant &v_e ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ss6b7ea7eb, "e")) : g->GV(e);

try {

LINE(10,(f_myfunc(NAMVAR(s_svib794f8ce, 1LL))));

} catch (Object e) {

if (e.instanceof(NAMSTR(s_ssae8717ad, "exception"))) {

v_e = e;

echo(NAMSTR(s_ss93e46d56, "catch!"));

} else {

throw;

}

}

return true;

}

#ifdef INFINITE_LOOP_DETECTION

#define LOOP_COUNTER(n)

#define LOOP_COUNTER_CHECK(n) \

if ((++lc & 1023) == 0) { \

check_request_timeout_ex(fi, lc); \

}

#define LOOP_COUNTER_CHECK_INFO(n) \

if ((++lc & 1023) == 0) { \

check_request_timeout_info(info, lc); \

}

#else

#define LOOP_COUNTER(n)

#define LOOP_COUNTER_CHECK(n)

#define LOOP_COUNTER_CHECK_INFO(n)

#endif

foreach

<?php

$a = 10;

if ($a == 10 ){

echo "10";

}

else

{

echo "else!";

}

A try catchに落ちた

変換されたファイル郡をみると、

*.tpl.*というファイルが増えてる。

Variant pm_php$test24_php(bool incOnce, LVariableTable* variables, Globals *globals) {

PSEUDOMAIN_INJECTION(run_init::test24.php, pm_php$test24_php);

LVariableTable *gVariables ATTRIBUTE_UNUSED = (LVariableTable *)g;

Variant &v_a ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ss27b9150a, "a")) : g->GV(a);

v_a = 10LL;

LINE(3,(pm_php$test24_tpl(false, variables, g)));

return true;

}

if

forとwhile

v_for_sum = 0LL;

{

LOOP_COUNTER(1);

for (v_a = 0LL; (not_more(v_a, 10LL)); v_a++) {

LOOP_COUNTER_CHECK(1);

{

v_for_sum += v_a;

}

}

}

v_while_sum = 0LL;

v_a = 10LL;

LOOP_COUNTER(2);

{

while (toBoolean(v_a)) {

LOOP_COUNTER_CHECK(2);

{

v_while_sum += v_a;

v_a--;

}

}

}

v_arr = s_sa50d82ba2;

{

LOOP_COUNTER(1);

for (ArrayIter iter3 = v_arr.begin(null_string, true); !iter3.end(); ++iter3) {

LOOP_COUNTER_CHECK(1);

iter3.second(v_val);

v_key.assignVal(iter3.first());

{

{

echo(toString(v_key));

echo(NAMSTR(s_ss8f4bca72, " => "));

echo(toString(v_val));

echo(NAMSTR(s_ss66d2232c, "\n"));

}

}

}

}

制御文

goto先生

ちっすちっす

PHPは、break 2;で

ループ2回ぶち抜きとかできる。

std::map っぽい

イテレータ

JSPみたいに、

echo に切り替わった。

hello <?php echo $a ?>

文字列ラベルを作ると、

gotoに変わる

A includeしているところ

include("test24.tpl");

前置インクリメントだと・・

文字列caseにすると・・・→

=== は、same() という関数になりました。

ディフォルトで、無限ループ検出器が働いている。

俺のコードに無限ループなんて無いっという人は、

無効にすればもっと早くなると思われる。

== は equal関数になりました。

ループカウンタの型は、 Variant なのが残念。

Variant &v_a ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ss27b9150a, "a")) : g->GV(a);

equal

==

same

===

なんで、コメントアウトされているか?

cls/baseinterface.h

cls/myclass.h

php/test26.cpp

php/test26.fws.h

php/test26.h

cls/baseclass.h

cls/myclass.h

php/test25.cpp

php/test25.fws.h

php/test25.h

とにかく長い!!

cls/baseinterface.h

cls/myclass.h

php/test26.cpp

php/test26.fws.h

php/test26.h

ベースクラスを

見て行きましょう。

cls/myclass.h

php/test11.cpp

php/test11.fws.h

php/test11.h

cls/baseclass.h

cls/myclass.h

php/test25.cpp

php/test25.fws.h

php/test25.h

cls/myclass.h

php/test11.cpp

php/test11.fws.h

php/test11.h

<?php

interface baseinterface

{

public function pubfunc($a);

}

class myclass implements baseinterface

{

public function pubfunc($a)

{

return $a + 3;

}

}

$class = new myclass();

$a = $class->pubfunc(10);

var_dump($a);

クラスはC++ネイティヴのクラスを利用。

それをラップする型に入れている。

ただし、メソッド呼び出しなどは自前で

メソッドを追跡している。

多分、magic method対策だと思われる。

<?php

class myclass

{

public $privar = 10;

public $pubvar = 20;

public function pubfunc($a)

{

return $a + $this->privar +

$this->pubvar;

}

}

$class = new myclass();

$a = $class->pubfunc(10);

/* SRC: test11.php line 3 */

FORWARD_DECLARE_CLASS(myclass);

extern const ObjectStaticCallbacks cw_myclass;

class c_myclass : public ObjectData {

public:

// Properties

int64 m_privar;

int64 m_pubvar;

// Class Map

DECLARE_CLASS_NO_SWEEP(myclass, myclass, ObjectData)

static const ClassPropTable os_prop_table;

c_myclass(const ObjectStaticCallbacks *cb = &cw_myclass) : ObjectData(cb, false), m_privar(10LL), m_pubvar(20LL) {}

public: Numeric t_pubfunc(CVarRef v_a);

DECLARE_METHOD_INVOKE_HELPERS(pubfunc);

};

ObjectData *coo_myclass() NEVER_INLINE;

継承

PHPで オブジェクト型への dynamic_cast がないからだと推測します。

C++で interface継承をする理由の一つに、

dynamic_castをするためだと思う。

hiphop PHPはメソッド名解決を含め自前で全部やっているので、わざわざコンパイラにしてもらう必要がなかったのではと思う。

interface

<?php

class baseclass

{

private function prifunc($a)

{

return $a + 1;

}

protected function protfunc($a)

{

return $a + 1;

}

public function pubfunc($a)

{

return $a + 1;

}

}

class myclass extends baseclass

{

public function pubfunc($a)

{

return $this->protfunc( $a + 2 ); //$a + 3

}

}

$class = new myclass();

$a = $class->pubfunc(10);

var_dump($a);

/* preface starts */

extern CallInfo ci_;

/* preface finishes */

/* SRC: test11.php line 3 */

IMPLEMENT_CLASS_NO_DEFAULT_SWEEP(myclass)

const InstanceOfInfo c_myclass::s_instanceof_table[] = {

{0x124B454009539DD2LL,1,"myclass",&cw_myclass},

};

const int c_myclass::s_instanceof_index[] = {

1,

0,-1,

};

CallInfo c_myclass::ci_pubfunc((void*)&c_myclass::i_pubfunc, (void*)&c_myclass::ifa_pubfunc, 1, 4, 0x0000000000000000LL);

Variant c_myclass::i_pubfunc(MethodCallPackage &mcp, CArrRef params) {

return invoke_meth_few_handler(mcp, params, &ifa_pubfunc);

}

Variant c_myclass::ifa_pubfunc(MethodCallPackage &mcp, int count, INVOKE_FEW_ARGS_IMPL_ARGS) {

if (UNLIKELY(mcp.obj == 0)) {

return ObjectData::ifa_dummy(mcp, count, INVOKE_FEW_ARGS_PASS_ARGS, ifa_pubfunc, coo_myclass);

}

c_myclass *self ATTRIBUTE_UNUSED (static_cast<c_myclass*>(mcp.obj));

if (UNLIKELY(count < 1)) throw_missing_arguments("myclass::pubfunc", count+1);

CVarRef arg0(UNLIKELY(count <= 0) ? null_variant : a0);

return (self->t_pubfunc(arg0));

}

const MethodCallInfoTable c_myclass::s_call_info_table[] = {

{ 0x4A7B5BE10021188ALL, 1, 7, "pubfunc", &c_myclass::ci_pubfunc },

{ 0, 1, 0, 0 }

};

const int c_myclass::s_call_info_index[] = {

1,

0,-1,

};

const ObjectStaticCallbacks cw_myclass = {

(ObjectData*(*)(ObjectData*))coo_myclass,

c_myclass::s_call_info_table,c_myclass::s_call_info_index,

c_myclass::s_instanceof_table,c_myclass::s_instanceof_index,

&c_myclass::s_class_name,

&c_myclass::os_prop_table,0,0,0,0x0

};

/* SRC: test11.php line 7 */

Numeric c_myclass::t_pubfunc(CVarRef v_a) {

INSTANCE_METHOD_INJECTION_ROOTLESS(myclass, myclass::pubfunc);

INTERCEPT_INJECTION("myclass::pubfunc", array_createvi(1, toVPOD(v_a)), r);

return ((v_a + m_privar) + m_pubvar);

}

namespace hphp_impl_splitter {}

ObjectData *coo_myclass() {

return NEWOBJ(c_myclass)();

}

Variant pm_php$test11_php(bool incOnce, LVariableTable* variables, Globals *globals) {

PSEUDOMAIN_INJECTION(run_init::test11.php, pm_php$test11_php);

LVariableTable *gVariables ATTRIBUTE_UNUSED = (LVariableTable *)g;

Variant &v_class ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ssc82dbd12, "class")) : g->GV(class);

Variant &v_a ATTRIBUTE_UNUSED = (variables != gVariables) ? variables->get(NAMSTR(s_ss27b9150a, "a")) : g->GV(a);

{

LINE(13,0);

const p_myclass &tmp0((p_myclass(((c_myclass*)coo_myclass()))));

v_class = tmp0;

}

{

LINE(14,0);

MethodCallPackage mcp0;

CVarRef obj0 = v_class;

mcp0.methodCall((obj0), NAMSTR(s_ss758adc76, "pubfunc"), 0x4A7B5BE10021188ALL);

const CallInfo *cit0 ATTRIBUTE_UNUSED = mcp0.ci;

Variant tmp1(((mcp0.ci->getMeth1Args())(mcp0, 1, NAMVAR(s_svi542bad8b, 10LL))));

v_a.assignVal(tmp1);

}

LINE(16,(x_var_dump(1, v_a)));

return true;

}

namespace hphp_impl_splitter {}

// Class tables

static const int64 cpt_static_inits[] = {

(int64)&NAMVAR(s_svid7a79683, 20LL),

(int64)&NAMVAR(s_svi542bad8b, 10LL),

};

static const ClassPropTableEntry cpt_table_entries[] = {

{0x1CA3E3D9527D20FALL,0,0,0,68,4,GET_PROPERTY_OFFSET(c_myclass, m_pubvar),&NAMSTR(s_ssa42bbae9, "pubvar") },

{0x27731D65F3F36A14LL,-1,1,0,68,4,GET_PROPERTY_OFFSET(c_myclass, m_privar),&NAMSTR(s_ss3b22d7c5, "privar") },

};

static const int cpt_hash_entries[] = {

// myclass hash

-1,-1,0,-1,1,-1,-1,-1,

// myclass lists

-1,

-1,

-1,

};

const ClassPropTable c_myclass::os_prop_table = {

7,1,-1,-1,-1,-1,9,0,

cpt_hash_entries+0,0,cpt_table_entries+0,cpt_static_inits

};

FORWARD_DECLARE_GENERIC_INTERFACE(baseinterface);

class c_baseinterface {

// public: virtual void t_pubfunc(CVarRef v_a) = 0;

};

A inferface継承していない

class myclass implements baseinterface

{

}

クラス

同じように、

それぞれクラスになる。

interface もクラスになる。

クラスの実態は、

すべて 本体のコードが書かれている cpp に書かれます。

とても、巨大なので、割愛します。

基本的に、

クラス変換と同じです。

変換された

ファイル郡に、

cls というのが増える。

A インスタンス構築

$class = new myclass();

FORWARD_DECLARE_CLASS(baseclass);

extern const ObjectStaticCallbacks cw_baseclass;

class c_baseclass : public ObjectData {

public:

// Properties

// Class Map

DECLARE_CLASS_NO_SWEEP(baseclass, baseclass, ObjectData)

c_baseclass(const ObjectStaticCallbacks *cb = &cw_baseclass) : ObjectData(cb, false) {}

public: Numeric t_prifunc(CVarRef v_a);

public: Numeric t_protfunc(CVarRef v_a);

public: virtual Variant t_pubfunc(Variant v_a);

DECLARE_METHOD_INVOKE_HELPERS(prifunc);

DECLARE_METHOD_INVOKE_HELPERS(protfunc);

DECLARE_METHOD_INVOKE_HELPERS(pubfunc);

};

ObjectData *coo_baseclass() NEVER_INLINE;

ベースクラスの

clsか増えました。

A 純粋仮想関数がコメントアウトされている。

B メソッド呼び出し

$a = $class->pubfunc(10);

C メソッド名は自前名前解決

magic method対策?

クラス定義だけ書いてある。

実態は、 test11.cpp にまとめられる

A 全部 public になってる。

private function prifunc($a)

{

return $a + 1;

}

protected function protfunc($a)

{

return $a + 1;

}

public function pubfunc($a)

{

return $a + 1;

}

Zzzzz....

magic method

staticメソッド

この節を書こうとした人は途中で

寝てしまいました。

global変数

この節を書こうとした人は途中で

寝てしまいました。

HipHop Virtual Machine

動的言語は、

本質的に静的言語より遅いんじゃない。

ただ研究が遅れているだけだ。

hiphop php がジェネレートする

C++ のコードについて簡単に見てきました。

結構頑張った最適化が

行われていると思います。

現在、 hiphop PHPは、

PHPをC++に変換し gcc でコンパイルしてます。

ただ、コンパイルに時間がかかったりするので、

それを解決する、 JIT が作られているそうです。

Hiphop VirtualMachineは、

インタプリタに比べ1.6倍早く、

コンパイラに比べて0.6倍の速度だそうです。

今後、その差は縮まっていくそうです。

まとめ

という名言があるそうです。

今後の、研究に期待したいところですね。

http://www.publickey1.jp/blog/11/phpjithiphop_virtual_machinefacebook.html

Learn more about creating dynamic, engaging presentations with Prezi