Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
PHPのOpcodeを 読んでみよう
Search
yasuaki640
October 08, 2023
Programming
1.9k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
PHPのOpcodeを 読んでみよう
yasuaki640
October 08, 2023
More Decks by yasuaki640
See All by yasuaki640
LeetCode x AIで始める コーディング面接対策
yasuaki640
0
76
PHPのFFIを使って簡単なメロディを演奏する
yasuaki640
0
890
TypeScriptで簡易DBを作ってみた
yasuaki640
1
320
Other Decks in Programming
See All in Programming
AIエージェントで 変わるAndroid開発環境
takahirom
2
760
AI時代の仕事技芸論〜ソフトウェア開発で「遊ぶように働く」職人的熟達のすすめ(スクフェス仙台 2026バージョン)
kuranuki
0
790
20260722_microCMSで考える、AI時代のコンテンツ運用設計
yosh1
0
190
これって Effect でできたのでは? / TSKaigi Mashup Kansai #2
susisu
0
130
jsmini JavaScript Engine を作ってみた話
yosuke_furukawa
PRO
0
280
Terraform標準の組織で AWS CDKをどう使うか
mu7889yoon
1
450
生成AIで帳票OCRが「簡単に」作れる時代になった?
kon_shou
0
190
Built Our Own Background Agent at LayerX #aidevex_findy
layerx
PRO
9
4.3k
音楽のための関数型プログラミング言語mimiumにおける多段階計算の活用
tomoyanonymous
1
380
Google Apps Script で Ruby を動かす
kawahara
0
120
複数の Claude Code が"放置"されてしまう問題をCLI ダッシュボードを自作して解決した話
sumihiro3
0
600
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
480
Featured
See All Featured
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
230
Heart Work Chapter 1 - Part 1
lfama
PRO
8
36k
Context Engineering - Making Every Token Count
addyosmani
9
1k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.1k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.4k
How GitHub (no longer) Works
holman
316
150k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
2
3.7k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
420
KATA
mclloyd
PRO
35
15k
Scaling GitHub
holman
464
140k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
420
Transcript
PHPのOpcodeを 読んでみよう ディップ株式会社 クライアントエンハンス課 渡邉泰曉 @yasuaki640
この発表のねらい 1. Opcodeを読む準備ができる 2. PHP処理系内部を垣間見、処理系に興味を持てる
Opcodeとは?(wikipediaより抜粋) (機械語に限らず)操作に関する命令のコード。 (中略) アセンブリ言語や仮想機械などの用語として用 いられる。 https://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%9A%E3%82%B3%E3%83%BC%E3%83%89
Opcodeとは?(PHPでのダンプ形式) ADD CV0($a) CV1($b) オペコード オペランド(引数)
Opcodeの扱われ方(概要) 1. PHPコードを解析し、AST(抽象構文木)を出力 2. ASTからOpcodeを生成 3. OpcodeをPHP VMが実行 <?php echo
"Hello"; ECHO string("Hello") RETURN int(1) array( 0: Stmt_Echo( exprs: array( 0: Scalar_String( value: Hello ) ... 解析 生成(emit) VMに渡され実行
Opcodeの扱われ方(OPcache使用時) - Opcodeが共有メモリにキャッシュされる - PHPコードの解析~ASTの生成を飛ばすため処理が速い!! <?php echo "Hello"; ECHO string("Hello")
RETURN int(1) array( 0: Stmt_Echo( exprs: array( 0: Scalar_String( value: Hello ) ... 解析 生成(emit) VMに渡され実行 ここだけ実行
Opcodeを読むメリット(個人の感想です) - (手っ取り早く)PHP処理系の挙動を垣間見れる - php-srcリーディングの取っ掛かりとしやすい
Opcodeダンプの設定 - PHP 7.1以降であれば拡張を入れず、簡単に Opcodeダンプを出力できる - 詳細はAppendixに記載
Opcodeを読む <?php $a = 1; $b = 2; $c =
$a + $b; echo $c;
Opcodeを読む <?php $a = 1; $b = 2; $c =
$a + $b; echo $c; $_main: ; (lines=6, args=0, vars=3, tmps=4) ; (before optimizer) ; /workspace/experimental.php:1-6 ; return [] RANGE[0..0] 0000 ASSIGN CV0($a) int(1) 0001 ASSIGN CV1($b) int(2) 0002 T5 = ADD CV0($a) CV1($b) 0003 ASSIGN CV2($c) T5 0004 ECHO CV2($c) 0005 RETURN int(1)
Opcodeを読む $_main: ; (lines=6, args=0, vars=3, tmps=4) ; (before optimizer)
; /workspace/experimental.php:1-6 ; return [] RANGE[0..0] 0000 ASSIGN CV0($a) int(1) 0001 ASSIGN CV1($b) int(2) 0002 T5 = ADD CV0($a) CV1($b) 0003 ASSIGN CV2($c) T5 0004 ECHO CV2($c) 0005 RETURN int(1) 実行時のメタ情報 ダンプされた Opcode
Opcodeを読む - PHP公式に各Opcodeの説明が記載 http://php.adamharvey.name/manual/ja/internals2.opcodes.php
Opcodeを読む 0000 ASSIGN CV0($a) int(1) 0001 ASSIGN CV1($b) int(2) 0002
T5 = ADD CV0($a) CV1($b) 0003 ASSIGN CV2($c) T5 0004 ECHO CV2($c) 0005 RETURN int(1) PHPスクリプト上の 実際の変数($a, $b) に値を代入
Opcodeを読む 0000 ASSIGN CV0($a) int(1) 0001 ASSIGN CV1($b) int(2) 0002
T5 = ADD CV0($a) CV1($b) 0003 ASSIGN CV2($c) T5 0004 ECHO CV2($c) 0005 RETURN int(1) 加算を実行し、 VM上の一時変数(T5)に 値を代入
Opcodeを読む 0000 ASSIGN CV0($a) int(1) 0001 ASSIGN CV1($b) int(2) 0002
T5 = ADD CV0($a) CV1($b) 0003 ASSIGN CV2($c) T5 0004 ECHO CV2($c) 0005 RETURN int(1) VM上の一時変数(T5)の値を PHPスクリプト上の 実際の変数($c)に代入
Opcodeを読む 0000 ASSIGN CV0($a) int(1) 0001 ASSIGN CV1($b) int(2) 0002
T5 = ADD CV0($a) CV1($b) 0003 ASSIGN CV2($c) T5 0004 ECHO CV2($c) 0005 RETURN int(1) 加算結果が代入された 変数に対しechoを実行
Opcodeを読む 0000 ASSIGN CV0($a) int(1) 0001 ASSIGN CV1($b) int(2) 0002
T5 = ADD CV0($a) CV1($b) 0003 ASSIGN CV2($c) T5 0004 ECHO CV2($c) 0005 RETURN int(1) PHP側で 暗黙的に付与されるreturn ※詳細は略
Opcodeのハンドラを読む - マニュアルに説明がないOpcodeもある - php-srcに、Opcodeのハンドラ(処理の実体)を探して 読む - 今回はハンドラの探し方まで紹介
Opcodeのハンドラを読む <?php function welcome(string $target): string { $hi = 'Welcome
to' . $target; return $hi; } echo welcome('PHP conference!'); $_main: (省略) 0000 INIT_FCALL 1 144 string("welcome") 0001 SEND_VAL string("PHP conference!") 1 0002 V0 = DO_UCALL 0003 ECHO V0 0004 RETURN int(1) welcome: (省略) 0000 CV0($target) = RECV 1 0001 T2 = CONCAT string("Welcome to") CV0($target) 0002 ASSIGN CV1($hi) T2 0003 VERIFY_RETURN_TYPE CV1($hi) 0004 RETURN CV1($hi) 0005 VERIFY_RETURN_TYPE 0006 RETURN null
Opcodeのハンドラを読む welcome: (省略) 0000 CV0($target) = RECV 1 0001 T2
= CONCAT string("Welcome to") CV0($target) 0002 ASSIGN CV1($hi) T2 0003 VERIFY_RETURN_TYPE CV1($hi) 0004 RETURN CV1($hi) 0005 VERIFY_RETURN_TYPE 0006 RETURN null 引数の型チェック?? (ドキュメントに説明がない)
Opcodeのハンドラを読む - php-srcのzend_vm_execute.hに実際の処理が書 かれている ZEND_{Opcode名}_SPEC_{オペランドの種別}_HANDLER
Opcodeのハンドラを読む static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNUSED_HANDLER (ZEND_OPCODE_HANDLER_ARGS) { オペコード名 オペランドの種別
Opcodeのハンドラを読む - ソースを読むだけではわからないことも多い - 本当にそのハンドラが呼ばれているのか? - デバッガを使う - 手順はネット上に豊富なため割愛
Opcodeのハンドラを読む
まとめ - PHPコードは内部でOpcodeにコンパイルされる - Opcodeを読むことは、php-srcリーディングなど深淵 の入り口におすすめ - パフォーマンスのため、OPcacheはちゃんと設定しよ う
採用やってます!!! - QRコードを読み取り、カジュアル面談しましょう!!
Appendix
参考にさせていただいた記事 - php-srcを読んでみよう - https://fortee.jp/phpcon-2022/proposal/1addf51d-6f72-4c96-9337-034ec6cc0643 - PHP による hello world
入門 - https://tech.respect-pal.jp/php-helloworld - PHP 7 Virtual Machine - https://www.npopov.com/2017/04/14/PHP-7-Virtual-machine.html - How to dump and inspect PHP OPCodes - https://php.watch/articles/php-dump-opcodes - Static Optimization of PHP bytecode (PHPSC 2017) - https://www.slideshare.net/nikita_ppv/static-optimization-of-php-bytecode-phpsc-2017 - Zend Engine 2 オペコード (PHP公式マニュアル) - http://php.adamharvey.name/manual/ja/internals2.opcodes.php - OPcache (PHP公式マニュアル) - https://www.php.net/manual/en/book.opcache.php - Implementing a Range Operator into PHP - https://phpinternals.net/articles/implementing_a_range_operator_into_php - Using CLion with php-src - https://dev.to/ramsey/using-clion-with-php-src-4me0
Opcodeダンプの設定 - .iniファイルでOPcacheの設定を有効にする - 今回はCLI版での実行を想定 zend_extension=opcache opcache.enable_cli=1
Opcodeダンプの設定 - スクリプト実行時にOpcodeダンプ出力のオプションを 渡す php -d opcache.opt_debug_level=0x10000 sample.php