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
70
PHPのFFIを使って簡単なメロディを演奏する
yasuaki640
0
870
TypeScriptで簡易DBを作ってみた
yasuaki640
1
310
Other Decks in Programming
See All in Programming
決定論的オーケストレーションの設計と実装 / Design and Implementation of Deterministic Orchestration
nrslib
4
1.4k
軽量Java基盤の設計 DIコンテナに頼らない、長期保守と1秒起動の実現 JJUG CCC 2026 Spring
macha64
0
540
Developing with AI Agents — Codex, Claude Code & Cowork Practical Guide
x5gtrn
PRO
0
1.3k
jQueryをバージョンアップする前に使いたいjQuery Migrate
matsuo_atsushi
0
560
ユニットテストの先へ:テスト技法で要求・仕様を整理するJava開発実践 / Beyond_Unit_Testing_Practical_Java_Development_Techniques_for_Organizing_Requirements_and_Specifications
shimashima35
0
410
AI時代のUIはどこへ行く?その2!
yusukebe
22
7.4k
ADKを使って簡単にAIエージェントを作ってみよう
k1mu21
0
270
Vue × Nuxt × Oxc どこまで使える?実運用の現在地
andpad
0
270
New "Type" system on PicoRuby
pocke
1
970
「なぜそう決めたのか」を残し続ける仕組み ― Notion AI カスタムエージェント × Slack連携による設計判断の自動記録 - NIKKEI Tech Talk #47
niftycorp
PRO
0
210
Oxcを導入して開発体験が向上した話
yug1224
4
320
不変条件と整合性境界—ビジネスが決める設計判断と実現パターン / Invariants and Consistency Boundaries
nrslib
14
5.6k
Featured
See All Featured
My Coaching Mixtape
mlcsv
0
150
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.9k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
230
Statistics for Hackers
jakevdp
799
230k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Marketing to machines
jonoalderson
1
5.5k
We Have a Design System, Now What?
morganepeng
55
8.2k
Six Lessons from altMBA
skipperchong
29
4.3k
Git: the NoSQL Database
bkeepers
PRO
432
67k
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
170
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
11k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
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