Introducing
Your new presentation assistant.
Refine, enhance, and tailor your content, source relevant images, and edit visuals quicker than ever before.
Trending searches
#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
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