はじめに
SwiftはAppleによって開発された全く新しいプログラミング言語です。WWDC 2014で稲妻のように現れたこのプログラミング言語は、またたく間に世界中のモバイルアプリ開発者の注目を集めました。
Swiftは衝撃的な登場だったことから突然現れた技術かのように捉えられることもありますが、開発が開始されたのは2010年だったと発表されています。また、Swiftが生まれたのはAppleが急に新たな領域に踏み出したというわけではなく、長年コンパイラ関連技術の開発に大きくコミットしてきた結果なのだと筆者は考えています。
本記事では、Appleのコンパイラ関連技術を振り返り、Swiftにどう繋がるのかを解説します。
対象読者
- Appleプラットフォームで動作するアプリ開発者
- Appleの技術に興味のある方
- Swiftに興味のある方
Objective-Cとコンパイラ
AppleはSteve Jobsの復帰以降、BSDベースのOS XやIntelアーキテクチャへの移行など非常に大胆な技術的な転換を多く行い成功させてきました。開発者はAppleの方向性に追従すればそれだけでよかったのです。しかしながら、新たなプログラミング言語を作るといった転換はSwiftが初めてです。Appleはなぜ新しいプログラミング言語を作ったのか?Swiftに至る道は、Appleのコンパイラ技術を振り返ることから紐解くことができます。
Objective-C 2.0からModern Objective-Cへ
AppleはWWDC 2006で従来のObjective-Cに大きな変更が追加された、Objective-C 2.0を発表しました。このアップデートでは、モダンなObjective-Cプログラミングを支えるプロパティやクラスエクステンション、fast enumerationなどが追加されています。このとき追加された機能はどれも現在のObjective-Cの人気において不可欠な要素ですが、現在に残っていないものがひとつだけあります。そう、ガベージコレクションです。
Objective-Cはメモリ管理に参照カウント方式を採用しています。特にiOS 4以前くらいからiOSアプリ開発を始めた方の中には苦しんだ経験をされた方は多いことでしょう。しかし、2006年の時点でObjective-Cにガベージコレクションがあったはずなのに、なぜiOSアプリ開発でメモリ管理に苦しむのか疑問に感じるのではないでしょうか?ガベージコレクションはOS Xのみのサポートで、iOSではサポートされることがありませんでした。そのため、iOSアプリ開発においてメモリ管理はプログラマの責任で、長らく頭の痛い問題のひとつでした。
そのような不遇な環境にも一筋の光明がさします。ARC(Automatic Reference Counting)とStatic Analyzerの登場です。ARCはコンパイル時に参照カウントを増減するコードを自動で埋め込みます。Static Analyzerを使えば、静的に導くことのできる潜在的なメモリリークを自動で検出できます。これらの機能の登場には、Appleが開発した全く新しいC/C++/Objective-CのコンパイラであるClangが大きく関わっています。
従来Objective-CのコンパイラはGCCを利用していましたが、拡張が難しいためAppleはClangを開発しました。このClangを内包したXcode 4.2のリリースにより、プログラマの負担は大きく軽減されます。従来は、プログラマが丁寧にメモリ管理を実装していたものが自動で管理されるように置き換えられ、メモリリークの有無の検査にはLeaks(メモリリークの検出ツール)などを実行しているアプリケーションに接続し、実際に動かしつつ計測することによってメモリリークを検出していたものが、自動で検査できるようになったのです。例えARCとはいえ実装によってはメモリリークしたり、Static Analyzerでは検出できないメモリリークが存在するため完璧なものではありませんでしたが、プログラマの負担が大きく削減されたのは紛れもない事実です。
Clangの導入がもたらしたものはメモリ管理の負担軽減に留まりません。C/C++に対するAppleの独自拡張であるBlocks(クロージャのようなもの)やObjective-CのModern syntaxなど、Appleはここ数年のWWDCで毎度といっていいほどObjective-Cになんらかのアップデートを加えてきました。これほどまでにObjective-C自体をアップデートできた理由は、自らコンパイラを開発していたからに他なりません。Objective-C 2.0からModern Objective-Cへの大きな進化における影の立役者がClangであることは明らかな事実です。
ClangでAppleがめざしたもの
Clangを語るうえで切っても切り離せない関係にあるものがバックエンドであるLLVMです。LLVMはコンパイル時やリンク時、実行時などあらゆる時点でプログラムを最適化できるコンパイラ基盤です。現在の最新版であるXcode 6.3.2のコンパイラにはフロントエンドにClangバックエンドにLLVMの組み合わせが使われていますが、LLVMが採用された当初はフロントエンドにはGCCが使われていました。
Objective-Cは非常に動的なことが特徴である言語のひとつです。例えば、実行時には全てのオブジェクトはid型とされるため実行時にクラスを拡張することや、実装を取り替えるなどといったインタプリタ型言語のような振る舞いが可能です。もちろんメソッドの実行に関しても同様です。NSObject
のperformSelector:
メソッドなどからは色濃くその特徴を見て取れることでしょう。このようにObjective-Cは動的な機能によって非常に柔軟なプログラムを書くことができます。
ですが、動的な特徴はいいことづくしではありません。通常コンパイラ言語は実行時のコストを下げるために実行コードを最適化します。しかしながら、Objective-Cでは実行時に多くのことが決まるため、コンパイル時に最適化を施しにくいというデメリットがありました。iPhoneによって勢いを取り戻したAppleにとって、モバイルでの体験の向上は最も大きい課題のひとつです。可能な限りアプリケーションに最適化を施し、体験を向上させたいたいというのが本音でしょう。
LLVMによって実現される柔軟な最適化はObjective-Cにとって、とても都合のよいものでした。しかし、当初はフロントエンドに使っていたGCCは巨大なソフトウェアであることが足かせとなり、Appleの求めるスピードでObjective-Cの性能を向上するのが難しくなりました。
そこでAppleはC/C++/Objective-C向けのLLVMフロントエンドであるClangを開発しました。Appleが短期間でObjective-Cを大幅にアップデートできたのは、Clangを開発したことにより、自らイニシアチブを持つことが可能になったことが大きいでしょう。
Apple自らがコンパイラを開発することは、プログラムにより高度な最適化を施すためにも、Objective-Cをより早く進化させるために必要不可欠でした。ハードウェアの機能を向上させることは言うまでもありませんが、その上で動作するソフトウェアに関しても根底の技術から研ぎ澄ますことによってiPhoneの高いユーザ体験は守られてきたとも言えます。LLVMとClangは、Appleのプロダクトを下支えするため重要な役割を担っていたということです。