2.Trueオブジェクト Oddball など - v8 ソースコードリーディング

include/v8.h

プリミティブ型の定義があるので見てみよう。

Handle
  • GC で追跡できるようにオブジェクトをハンドルで管理する。
  • GC がオブジェクトを移動する可能性があるので参照ではなくてハンドル。
  • Handle は値渡しで使われ heap に確保されない
  • Handle は Local と Persistent 2種類ある 後述
Local
  • 軽量な Handle
  • スタックに allocate される
  • HandleScope で寿命管理される
Persistent
  • Handle
HandleScope
  • scope とは Handle のコンテナ
  • スタックに allocate される
Script
StackTrace
  • The information collected is a snapshot of the execution stack and the information remains valid after execution continues.
    • とあるから実行時オーバーヘッドがあるってことかな。

StackFrame

StackFrame までクラスなのね。内部表現は違うだろうけど。

Value

JavaScript の全ての値、オブジェクトの親クラス。継承ありきなら即値 integer とかないのかな。
- V8EXPORT bool IsUndefined() const; なんてメソッドも。

  • V8EXPORT Local ToBoolean() const;
  • V8EXPORT Local ToNumber() const;
    • この手のメソッドは Mosh でも同じだ

Primitive

class Primitive : public Value { };

Boolean

少し詳細を追ってみよう。

class Boolean : public Primitive {
 public:
  V8EXPORT bool Value() const;
  static inline Handle<Boolean> New(bool value);
};
Boolean オブジェクト作る
Handle<Boolean> Boolean::New(bool value) {
  return value ? True() : False();
}


True() は

v8::Handle<Boolean> True() {
  i::Isolate* isolate = i::Isolate::Current();
  if (!EnsureInitializedForIsolate(isolate, "v8::True()")) {
    return v8::Handle<Boolean>();
  }
  return v8::Handle<Boolean>(
      ToApi<Boolean>(isolate->factory()->true_value()));
}

true_value() はマクロで定義されている heap.h

  V(Object, true_value, TrueValue)

実体はここかな

  { MaybeObject* maybe_obj = CreateOddball("true",
                                           Smi::FromInt(1),
                                           Oddball::kTrue);
    if (!maybe_obj->ToObject(&obj)) return false;
  }
  set_true_value(obj);

CreateOddball の引数は順に to_string, to_number, byte kind.
Oddball は null, undefined, true, false を表すクラスらしい。定数だし即値オブジェクトであると予想。

k prefix は定数だよね。

  static const byte kFalse = 0;
  static const byte kTrue = 1;
  static const byte kNotBooleanMask = ~1;
  static const byte kTheHole = 2;
  static const byte kNull = 3;
  static const byte kArgumentMarker = 4;
  static const byte kUndefined = 5;
  static const byte kOther = 6;

Oddball::Initialize は Oddball::set_kind などに値を渡すだけ。

MaybeObject* Oddball::Initialize(const char* to_string,
                                 Object* to_number,
                                 byte kind) {

本丸は近い。

void Oddball::set_kind(byte value) {
  WRITE_BYTE_FIELD(this, kKindOffset, value);
}
#define WRITE_BYTE_FIELD(p, offset, value) \
  (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)

#define FIELD_ADDR(p, offset) \
  (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)

結局 (byte*)this + kKindOffset(定数) - kHeapObjectTag に1byte書き込んでると。即値オブジェクトだ。
kHeapObjectTag を引いているので HeapObject は heap に割り当てられるオブジェクトでポインタ末尾にタグがあるのだろう。GaucheMosh と同じ。