2012年2月29日水曜日

V8 JavaScript Engine libraries.cc

V8と言って思い浮かべるのがエンジンなのか、JavaScriptなのか、と言うと私はJavaScript。と言う訳で今回はV8 JavaScript Engineについて調査。

 V8をビルドするとobj/releaseもしくはobj/debug以下にlibraries.ccexperimental-libraries.ccと言うソースコードとそのビルド結果となるlibraries.oexperimenta-libraries.oいう合計4個のファイルが生成される。これは一体どうやって作られて、どんな目的のモノなのであろうか。

 まずはビルド時のログ出力をlibrariesをキーに検索すると、以下のような出力がある事が分かる(ちなみに、以下の出力はscons d8 mode=debugでビルドした時のもの。他の場合でも同じだとは思う)。
JS2C(["obj/debug/libraries.cc"], ["src/runtime.js", "src/v8natives.js", "src/array.js", "src/string.js", "src/uri.js", "src/math.js", "src/messages.js", "src/apinatives.js", "src/date.js", "src/regexp.js", "src/json.js", "src/liveedit-debugger.js", "src/mirror-debugger.js", "src/debug-debugger.js", "src/macros.py"])
g++ -o obj/debug/libraries.o -c -fno-rtti -fno-exceptions -fvisibility=hidden -Wall -Werror -W -Wno-unused-parameter -Woverloaded-virtual -Wnon-virtual-dtor -pedantic -m32 -g -O0 -ansi -DV8_TARGET_ARCH_IA32 -DENABLE_DISASSEMBLER -DDEBUG -DENABLE_DEBUGGER_SUPPORT -DV8_ENABLE_CHECKS -DOBJECT_PRINT -Iobj/debug -Isrc -Isrc obj/debug/libraries.cc
JS2C(["obj/debug/experimental-libraries.cc"], ["src/proxy.js", "src/collection.js", "src/macros.py"])
g++ -o obj/debug/experimental-libraries.o -c -fno-rtti -fno-exceptions -fvisibility=hidden -Wall -Werror -W -Wno-unused-parameter -Woverloaded-virtual -Wnon-virtual-dtor -pedantic -m32 -g -O0 -ansi -DV8_TARGET_ARCH_IA32 -DENABLE_DISASSEMBLER -DDEBUG -DENABLE_DEBUGGER_SUPPORT -DV8_ENABLE_CHECKS -DOBJECT_PRINT -Iobj/debug -Isrc -Isrc obj/debug/experimental-libraries.cc
 どうもJS2Cでccファイルを生成して、その後にg++でビルドしている様子。JS2Cと言う関数名からするとJavaScriptをCに変換しているのであろう。そのJS2Cはtools/js2c.pyファイルに定義されてて、そのファイルの先頭には以下の様なコメントがある。
# This is a utility for converting JavaScript source code into C-style
# char arrays. It is used for embedded JavaScript code in the V8
# library.
 つまり、JavaSciptコードをC形式の文字列配列に変換する、と言う事でJavaScript関数をCの関数に変換している訳ではないようなので、ちょっとがっかり。

 とりあえずJS2Cの第二引数に与えられているjsもpyもsrc以下と言う事なのでsrcフォルダを見てみると、jsもpyも全てそこに存在している。とりあえずv8natives.jsの中身を見てみると、どうやらJavaScriptコードの様子。。。なのだが微妙に違う記法が混じっていて、関数名の先頭に%記号が付いている。。。。こんなのありだっけか?と思ったが、恐らくpyの方で何かしらの変換をするのかも知れない。

// Helper function used to install functions on objects.
function InstallFunctions(object, attributes, functions) {
  if (functions.length >= 8) {
    %OptimizeObjectForAddingMultipleProperties(object, functions.length >> 1);
  }
  for (var i = 0; i < functions.length; i += 2) {
    var key = functions[i];
    var f = functions[i + 1];
    %FunctionSetName(f, key);
    %FunctionRemovePrototype(f);
    %SetProperty(object, key, f, attributes);
    %SetNativeFlag(f);
  }
  %ToFastProperties(object);
}
とりあえずsrcフォルダ以下でOptimizeObjectForAddingMultiplePropertiesを検索キーとしてgrepをかけてみると以下のファイルが見つかった(subversion関連は除外)。
./src/v8natives.js
./src/runtime.cc
./src/runtime.h
./src/math.js
どうもOptimizeObjectForAddingMultiplePropertiesはruntime.ccで定義されているcの関数である事が分かった。と言う事は%が先頭についた関数はcで定義された関数を直接記述する特別な記法なのかも知れない。

次にlibraries.ccの中を見ると以下の通りで、正確にはsources[]の中身を見る必要があるが、やはりスクリプトをC形式の文字列データに置き換えて、V8からアクセス出来る様にしている様子。
// Copyright 2011 Google Inc. All Rights Reserved. 
// This file was generated from .js source files by SCons.  If you
// want to make changes to this file you should either change the
// javascript source files or the SConstruct script.
#include "v8.h"
#include "natives.h"
#include "utils.h"
namespace v8 {
namespace internal {
static const byte sources[] = { .....(数値の羅列).....};
static const char* raw_sources = reinterpret_cast<const char*>(sources);  // const byteをconst charにキャスト
  template <>
  int NativesCollection<CORE>::GetBuiltinsCount() { // ビルトイン関数の個数
    return 14;
  }
  template <>
  int NativesCollection<CORE>::GetDebuggerCount() {  // デバッガー関数の個数
    return 3;
  }
  template <>
  int NativesCollection<CORE>::GetIndex(const char* name) { // オブジェクト名からインデックスを導出
    if (strcmp(name, "liveedit") == 0) return 0;
 。。。
    if (strcmp(name, "json") == 0) return 13;
    return -1;
  }
  template <>
  int NativesCollection<CORE>::GetRawScriptsSize() { // 生スクリプトサイズ
    return 238136;
  }
  template <>
  Vector<const char> NativesCollection<CORE>::GetRawScriptSource(int index) { // 生スクリプトソースをインデックスをキーに取得
    if (index == 0) return Vector<const char>(raw_sources + 144015, 15179);
 。。。
    if (index == 13) return Vector<const char>(raw_sources + 138135, 5880);
    return Vector<const char>("", 0);
  }
  template <>
  Vector<const char> NativesCollection<CORE>::GetScriptName(int index) { // スクリプト名をインデックスをキーに取得
    if (index == 0) return Vector<const char>("native liveedit.js", 18);
 。。。
    if (index == 13) return Vector<const char>("native json.js", 14);
    return Vector<const char>("", 0);
  }
  template <>
  Vector<const byte> NativesCollection<CORE>::GetScriptsSource() { // スクリプトソースを取得
    return Vector<const byte>(sources, 238136);
  }
  template <>
  void NativesCollection<CORE>::SetRawScriptsSource(Vector<const char> raw_source) { // 生スクリプトの設定
    ASSERT(238136 == raw_source.length());
    raw_sources = raw_source.start();
  }
}  // internal
}  // v8
 しかし、スクリプトコードをV8から見る事がどんな状況で必要なのだろうか?ここのスクリプトコードをJITコンパイルしてからbuilt-inオブジェクトのメソッドは実行されている?少なくともbuilt-in関数のソースコードはJavaScriptでは見える必要はないので、JITが有力である気がする。となると独自のbuilt-in関数を組み込む場合にはjsファイルを作成して、SConsのスクリプトを書き換えれば、追加が出来る様になるとか?

うーん、もう少し調べたいが、遅いので今日はこれまで。

2012年2月27日月曜日

Webinos Demo Series #4: Cardio Hills – Remote Sensors

原文リンク
ヘルスケアや個人トレーナーサービスを例にあげた、webベースのリモートセンシングのデモらしい。心拍数のようなプライバシーに関わる様な情報を自分が洗濯した人と共有する事が出来る(webinosではプライバシーや公開対象の人似ついての制御を提供する)。
内容的には良く聞く様なデモシナリオなのでそんなに興味がある訳ではないし、残念ながらデモは観られない(というかどこにデモがある??)のでどんなシステム構成かは不明だが、リモートのセンサーに外部からアクセス出来ると言う事はセンサー側がサーバになる訳なんだろう。と言う事はかなりの省電力を意識した設計にするんだろうな。
こういう話から超小型のOSを一昔前にMITだかのアメリカの大学で開発していたな〜、どうなったんだろうな〜、と懐かしく思ったのだが、そのOSの名前が全く思い出せない。。。

と思った数分後に思い出した。TinyOSだ。
サイトを見ると2010年のリリースを最後にGoogle codeに移動したらしい。

2012年2月22日水曜日

How to invoke v8 engine on chromium

少しWebKitから外れて、chromiumの調査をしてみる。

気になっていたのはchromiumのWebKitとv8の関係。WebKitはJavaScriptCoreを持っているのだが、一部を流用してv8が動いているのか、それともv8単体でJavaScriptを実現しているのか。そして、WebKitとv8の繋ぎはどうなっているのか。
とりあえずWebKitとv8の繋ぎをコードを追っかけてみた結果が下のシーケンス図。


WebCoreのScriptElementからScriptControllerのevaluate()を実行しているが、このScriptControllerはv8用とjs用の2種類が用意されていて、chromiumではv8用のコードがビルド時に使われ、そのままv8に流れて行く事になる。
次にV8Proxyでv8のライブラリを呼び出してv8の機能でプリコンパイル、コンパイル、実行、と処理を行っている。最終的な実行はi:Executtionで行っている様子。この構成を見る限り、v8は単独でJavaScriptを実現している様だ。まあ、v8のスタンドアローン版もある訳だし、敢えてブラウザの場合だけJavaScriptCoreと連動するってのも変な構成だし、至極当たり前な流れだ。

次はv8はJITコンパイラな訳だから、ネイティブコンパイルする条件を調べたい。

(2/22追記)
chromiumのコードにprintf()を追加してビルドしてみて分かったのだが、どうもV8Proxyから左側はchromiumのビルド時にターゲットから外れている様子。調べ直しだな。。。

(2/23追記)
v8はJITコンパイルするけれど、Firefoxのとは違って全て初回実行時にネイティブビルドすると言う事が分かった。全て初回ビルドか。。。



2012年2月21日火曜日

WebKitGtk Build on Ubuntu11.10 Part 2

pixmanが取得出来ない問題は時間帯を変えると、すんなり通った。。。
しかし、pixbufで以下のエラーが。。。

make[4]: *** `all-am' に必要なターゲット `GdkPixbuf-2.0.typelib' を make するルールがありません.  中止.
加えてlibsoupでも

make[2]: *** ターゲット `/usr/share/gobject-introspection-1.0/Makefile.introspection' を make するルールがありません.  中止.
at-spi2-coreでも

make[2]: *** `Atspi-2.0.gir' に必要なターゲット `/usr/bin/g-ir-scanner' を make するルールがありません.  中止.
こんなエラーでmakeが失敗する。。。

少なくとも/usr/share/gobject-introspection-1.0なるディレクトリは存在しない。
>  sudo apt-get install gobject-introspection
とかやってみるとインストールが始まる。。。make時のログ出力を確認すると

checking for gobject-introspection... yes
と出力されているが、うまくチェック機構が動作していないのだろうか。。。

とりあえず、状況を変更したので再度
> Tools/Scripts/update-webkitgtk-libs
を実行してみると、何故かpixbufもうまくmakeできる様になった。成功するのは良いんだけれども、原因が分からないまま成功するのは気持ちがいいモノではないなあ。その勢いで今までconfigureすら動かなかったものまで動作し始めて、また完了まで時間がかかりそうなので、今日はここまで。
(追記)
すべて正常にインストールが完了した様子。
明日はようやくWebKit本体のビルドが出来る。



2012年2月18日土曜日

WebKitGtk Build on Ubuntu11.10 Part 1

Gtk版のWebKitが欲しいので、ビルドしようとトライしていたのだが、Ubuntu10.04では必要なライブラリをインストール出来ず(正確にはインストールできるが色々な物を破壊してしまう。。)挫折。Ununtu11.04でもやってみて何とかウィンドウが表示される所までは行ったのだが、何故かページロードが出来ないし、裏では色々とエラー吐き撒くっているので、ちょっと微妙。と言う訳でビルドが出来ないのはUbuntuのバージョンが古いからという勝手な理由付けで、今回はUbuntu11.10で再チャレンジ(本当はもっとLinuxについて調べておくべきだとは思うんだが、時間がない)。
ビルド環境となるUbuntu11.10は以下の通りVirtualBox上で実行。
  • Ubuntu11.10 on VirtualBox on MacBookAir (Mac OS X 10.6.8)
ここの内容に従って環境構築。

Install the base WebKitGTK+ dependencies
apt-getはUbuntu10.04では色々とインストール出来なかったのだが、今回は特にエラーも出ずに全てインストール成功。
Install the jhbuild module dependencies
ここもapt-getはエラーなく完了。Ubuntu10.04でもエラーは出なかった筈。
ここでGitをインストールしていない、WebKitのソースコードを取得していない(^^;)のでインストールとチェックアウト。
> sudo apt-get install git-core
> cd webkit
> git clone git://git.webkit.org/WebKit.git WebKit
チェックアウトに時間がかかるので取り敢えずここまで。
(追記)
と思ったが、並行してnightly buildから取ってきて残りの手順を実施してみる。

> Tools/Scripts/update-webkitgtk-libs
どうもpixmanのwgetで応答がないので再試行を繰り返している。。。cairographics.orgにはアクセス出来ている様なのだが、ダウンロードが出来ない様子。
Firefox on Ubuntu11.10で該当URLにアクセスしてみてもやはりダウンロードできない。Chrome on MBAでもcairographics.orgにアクセス出来ず。
他のチェックアウトは成功するので、サーバメンテでもしているのだろう。あとで、pixmanのためにやり直さないと。。。
とりあえず、時間がないのでここまで。





WebKit Page Cache I - The Basics 抄訳

WebKit Page Cache I – The Basics
Page Cacheの内部動作を調べる必要があったので、上記記事を読んでみた。ざっと見ただけで内部動作については書かれていない事は分かったが、取り敢えずちょこっとピックアップして和訳。

Page Cache Overview
  • Page Cache=Firefoxの"Back-Forward Cache"、"bfcache"、Operaの"Fast History Navigation"と呼ばれる。
  • WebKitの"Back/Forward List"と"Page Cache"は違う(らしい)。
  • Page Cacheはウェブをよりスムーズに移動出来る様にするためのエンドユーザ向けの機能。
  • "HTTP sense"、"disk cache"、"memory cache"における"cache"とは異なる。
  • Page Cacheは「あるページを移動する時に"一時停止"し、そのページに戻ってきた時に"再生"する」機能。
  • 新しいページに遷移する場合、前のページのDOM、JavaScript、プラグイン、画像等はクリアされてしまうと、戻るボタンで戻ってくると再度これらリソースをネットワーク上から取得して、ページを再構築しなければならず、非効率。
  • 以前のページのリソースを(戻るボタンを押された場合のために)解放せずに維持しておくのがPage Cache。
Why Wouldn't Work?
  • Page Cacheがそんなに素晴らしいものならば、新しいページに遷移する時にWebKitは常にPage Cacheを使わないのか?
  Some Pages aren't Interesting
  • ページロードが未完了、もしくはエラーの場合や、他のURLにリダイレクトするページの場合にはPage Cacheは動作しない。
  Some Pages are Complicated
  • ウェブページはPage Cacheされる事を想定されていないかも知れないため、"一時停止"する事が難しい場合もある。WebKitが"一時停止"できないネイティブコードを持つプラグインを持つ場合や、WebKitが履歴上キャッシュ管理していない複数フレームを持つページ等があげられる。
  Some Pages are Secure
  • WebKitは全てのHTTPSサイトをPage Cacheから展開する事を許可していない。
  Planned Improvements
  • revision 48036では主要な制約が解消され、フレームを持ったページのPage Cacheが可能。
  • Plug-inサポートは計画中改善の中の大きなアイテム。
Unload Handlers
  • unloadイベントは、ユーザがページをクローズした時にページにcleanup処理をさせるために設計されたもの。
  • Page Cache内にページを移動させる前に、ブラウザはunloadイベントを発火させる事ができない。
  • もしブラウザがunloadイベントを行わずにPage Cacheにページを移動させるならば、そのページは"一時停止"されて隠れている間にブラウザによって解放されるかも知れず、その場合cleanup処理は決して動作しない。
  • unloadイベントの目的はページが閉じられる時の重要な処理を許可する事であり、全ての主要ブラウザはそのようなページをPage Cacheに移動する事を拒絶しており、ユーザ操作上のインパクトに繋がる。

2012年2月14日火曜日

The Vehicle API by webinos

The Vehicle API – pushing borders of Web applications

車内はFlexRay, CAN,MOST等の異なるネットワークが存在し、Gatewayを経由して相互に接続している。それらのネットワークへのアクセスを提供する場合には安全機能の妨げにならない事を保証する必要がある。

よいエントリーポイントとしてはヘッドユニットがあるが、駐車時の後方距離センサーのデータを利用して物体までの距離をディスプレイに表示する場合にはソフトリアルタイムメッセージが必要となる(のでリアルタイム性を損なわない注意が必要)。そこでwebinos APIを経由した車両バスへのアクセスを制御し、車両情報への安全なデータアクセスを提供する。今のところ、要求される安全性を確保するためヘッドユニット内でのデータ利用に制限している。

webinosプラットフォームであるVehicle APIの最初のリリースでは車両データの読み取りと、オンボードナビゲーションシステムとの連携機能にフォーカスしている。Vehicle APIはW3C仕様に沿った設計でイベントモデルをベースとしている。現在速度や縦加速度はW3CのGeolocationやDevice Orientation APIが提供するため、Vehicle APIでは扱わず、以下のデータ等を扱う。
  • 静的車両データ(型式、 モデル、燃料やトランスミッションのタイプ)
  • 距離センサーデータ
  • トリップコンピュータデータ(平均速度、燃費、走行距離、走行可能距離)
  • 気候データ(エアコンや排気口)
  • 制御データ(ワイパーやライトの状態)
  • ギアデータ
  • ナビゲーションデータ(目的地までの距離、経路案内のキャンセル)
HTML、CSS、JavaScriptで作成された駐車時の物体距離センサー情報を利用したデモを作成している。

W3C仕様に沿った仕様作りを意識してはいるものの、W3Cの仕様にまで持って行く計画があるかどうかも分からない状況であり、今後も少しは気にして見ておいた方が良さそう。また、BMWが仕様作成したと言う点が興味深い。他者と協力して車両情報APIの主導権を握って置きたいのかも知れない。この辺のAPIが固まって一般に公開され、普及してしまうと、車載用アプリも一般ユーザが軽く作れる状況になってしまって、ナビメーカーはさあ大変、な状況になりそう。

まあ、その前にデータ取得だけとは言え、データの組み合わせ次第では幾らでもプライバシー侵害が出来てしまうので、セキュリティが重要になってくると思われる。でも、セキュリティを維持するために使い勝手を損なうのでは微妙なのでユーザビリティを維持、もしくは向上させる事が可能なセキュリティシステムとか、今後必要になってくるかも知れない。

2012年2月2日木曜日

WebKit on Ubuntu10.04

checking for BASE_DEPENDENCIES... configure: error: Package requirements (glib-2.0 >= 2.28.0 atk >= 1.30 pango >= 1.24.0 cairo >= 1.10.0 cairo-gobject >= 1.10.0 gdk-pixbuf-2.0 >= 2.22.0) were not met:

Requested 'gdk-pixbuf-2.0 >= 2.22.0' but version of GdkPixbuf is 2.20.1
上記はTools/Script/update-webkitgtk-libsを実行した時のエラー。

gdk-pixbuf-2.22.1をダウンロード。しかしconfigureでエラー。glib2.25.5以降が必要とのことだが、WebKitでは2.28.0以降が求められているので、ここからダウンロードしてビルド&インストール。

再度、gdk-pixbufにトライするがconfigureで以下のエラー。

checking for TIFFReadRGBAImageOriented in -ltiff... no
checking for TIFFWriteScanline in -ltiff... no
checking for TIFFFlushData in -ltiff34... no
configure: WARNING: *** TIFF loader will not be built (TIFF library not found) ***
configure: error:
*** Checks for TIFF loader failed. You can build without it by passing
*** --without-libtiff to configure but some programs using GTK+ may
*** not work properly
sudo apt-get install libtiff4-dev
でライブラリをインストールしてみると./configureは成功。
その後、gdk-pixbuf-2.22.1のビルド&インストールも成功。

再度、Tools/Script/update-webkitgtk-libsを実行する。
あれ?同じエラーが出る。。。パスに問題あるのか?
Requested 'gdk-pixbuf-2.0 >= 2.22.0' but version of GdkPixbuf is 2.20.1

とりあえず今日はここまで。