IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

Google Chrome の JavaScript エンジン V8 を試す

(基本だらだら進行で、過程を追記していきます)

Google Chrome が出ました

Google ChromeJavaScript エンジンが刷新されたということで、その JavaScript エンジン V8 についていろいろ調べてみようと思います。
Issues - v8 - V8 JavaScript Engine - Monorail

ビルドしてみる

まず、 svn からソースを持ってくる

$ svn co http://v8.googlecode.com/svn/trunk/ v8

おおお。以外と少ない
で、 trunk の中に入って

$ cd v8

scons でビルド(scons が入ってない人は、 port や apt-get で入れる)

$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o obj/release/third_party/jscre/pcre_compile.o -c -ansi -w -fno-strict-aliasing -O2 -fno-rtti -fno-exceptions -ansi -w -fno-strict-aliasing -O2 -DENABLE_LOGGING_AND_PROFILING -DSUPPORT_UTF8 -DNO_RECURSE -DSUPPORT_UCP src/third_party/jscre/pcre_compile.cpp
:
:
ranlib libv8.a

libv8.a が出来た。ここまでは順調

Shell をビルドしてみる

scons のオプションを見る

$ scons --help
scons: Reading SConscript files ...
scons: done reading SConscript files.

mode: compilation mode (debug, release)
    default: release
    actual: release

sample: build sample (shell, process)
    default: 
    actual: 

env: override environment settings (NAME1:value1,NAME2:value2)
    default: 
    actual: 

toolchain: toolchain (gcc, msvc)
    default: gcc
    actual: gcc

simulator: simulator (arm, none)
    default: none
    actual: none

arch: arch (arm, ia32)
    default: ia32
    actual: ia32

library: library (static, shared)
    default: static
    actual: static

wordsize: wordsize (64, 32)
    default: 32
    actual: 32

snapshot: snapshot (on, off)
    default: off
    actual: off

os: os (linux, macos, win32)
    default: macos
    actual: macos

いろいろとあるが sample フラグで shell を作れるっぽいことが分かる
shell をビルドする

$ scons sample=shell
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o shell obj/sample/shell/release/shell.o -L. -lv8 -lpthread
scons: done building targets.

shell.o と libv8 と libpthread をリンクして完了。 shell というバイナリが出来た。
実行してみる。

$ ./shell 
V8 version 0.2.5
> for (var n in function () { return this } ()) print(n)
n
load
quit
print
version
> quit()

おおおおお。 JavaScript が動いた

shell のソースを見てみる

shell.cc をエディタで開く

$ vim samples/shell.cc

209 行くらいのシンプルなファイルだ。
とりあえず雰囲気だけ分かった。

Hello, world を雰囲気で書いてみる

雰囲気だけ分かったので、雰囲気で Hello, world してみる

// v8.h を読み込む
#include <v8.h>

v8::Handle<v8::Value> Print(const v8::Arguments& args);

int main(int argc, char* argv[]) {

  // 準備
  v8::HandleScope handle_scope;

  // グローバルオブジェクトの生成
  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();

  // 関数名の生成
  v8::Handle<v8::String> str_print = v8::String::New("print");
  // 関数オブジェクトの生成
  v8::Handle<v8::FunctionTemplate> fn_print = v8::FunctionTemplate::New(Print);
  // グローバルオブジェクトのプロパティに関数を設定
  global->Set(str_print, fn_print);

  // グローバルオブジェクトから環境を生成
  v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
  // 環境からスコープを生成
  v8::Context::Scope context_scope(context);

  // 実行する文字列を生成
  v8::Handle<v8::String> str = v8::String::New("print('Hello, world!')");
  // Undefined を生成(ファイル名がないから)
  v8::Handle<v8::Primitive> undefined = v8::Undefined();
  // コンパイル
  v8::Handle<v8::Script> script = v8::Script::Compile(str, undefined);

  // 実行
  v8::Handle<v8::Value> result = script->Run();

  // 終了
  return 0;
}

// 関数オブジェクト print の実体 
v8::Handle<v8::Value> Print(const v8::Arguments& args) {
  v8::String::AsciiValue str(args[0]);
  printf("%s\n", *str);
  return v8::Undefined();
}

ビルドする(-L と -I は適宜)

$ g++ helloworld.cc -L. -lv8 -Isrc

おお。成功

$ ./a.out
Hello, world!

おおおお。動いた

gdb で追いかけてみる

デバッグビルドする

$ scons mode=debug

こんどは、 libv8_g.a というファイルが出来た。
さっきの helloworld.cc のデバッグ版を作る

$ g++ -O0 -g helloworld.cc -L. -lv8_g -Isrc

で、 gdb コマンドで実行

$ gdb ./a.out
GNU gdb 6.3.50-20050815 (Apple version gdb-768) (Tue Oct  2 04:07:49 UTC 2007)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin"...Reading symbols for shared libraries .... done

(gdb) b main
Breakpoint 1 at 0x25c1: file helloworld.cc, line 33.
(gdb) r
Starting program: /Users/amachang/v8/a.out 
Reading symbols for shared libraries +++. done

Breakpoint 1, main (argc=1, argv=0xbffff9b4) at helloworld.cc:33
33	  v8::HandleScope handle_scope;
(gdb) s
v8::HandleScope::HandleScope (this=0xbffff940) at v8.h:397
397	  }
(gdb) 
v8::HandleScope::HandleScope (this=0xbffff940) at v8.h:395
395	  HandleScope() : previous_(current_), is_closed_(false) {
(gdb) 
396	    current_.extensions = 0;
(gdb) 
397	  }
(gdb) 
0x00022ac1 in v8::HandleScope::HandleScope (this=0xbffff940) at v8.h:397
397	  }
(gdb) 
main (argc=1, argv=0xbffff9b4) at helloworld.cc:35
35	  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
(gdb) 
v8::ObjectTemplate::New () at src/api.cc:824
824	  return New(Local<FunctionTemplate>());

おおお