google_javascript_engine_v8_阅读笔记

Utils::OpenHandle:

#define MAKE_OPEN_HANDLE(From, To) \
  v8::internal::Handle<v8::internal::To> Utils::OpenHandle(\
    const v8::From* that) { \
    return v8::internal::Handle<v8::internal::To>( \
        reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that))); \
  }

MAKE_OPEN_HANDLE(Template, TemplateInfo)
MAKE_OPEN_HANDLE(FunctionTemplate, FunctionTemplateInfo)
MAKE_OPEN_HANDLE(ObjectTemplate, ObjectTemplateInfo)
MAKE_OPEN_HANDLE(Signature, SignatureInfo)
MAKE_OPEN_HANDLE(TypeSwitch, TypeSwitchInfo)
MAKE_OPEN_HANDLE(Data, Object)
MAKE_OPEN_HANDLE(RegExp, JSRegExp)
MAKE_OPEN_HANDLE(Object, JSObject)
MAKE_OPEN_HANDLE(Array, JSArray)
MAKE_OPEN_HANDLE(String, String)
MAKE_OPEN_HANDLE(Script, Object)
MAKE_OPEN_HANDLE(Function, JSFunction)
MAKE_OPEN_HANDLE(Message, JSObject)
MAKE_OPEN_HANDLE(Context, Context)
MAKE_OPEN_HANDLE(External, Foreign)
MAKE_OPEN_HANDLE(StackTrace, JSArray)
MAKE_OPEN_HANDLE(StackFrame, JSObject)

#undef MAKE_OPEN_HANDLE

  

Utils::ToLocal:

#define MAKE_TO_LOCAL(Name, From, To)                                       \
  Local<v8::To> Utils::Name(v8::internal::Handle<v8::internal::From> obj) { \
    ASSERT(obj.is_null() || !obj->IsTheHole());                             \
    return Local<To>(reinterpret_cast<To*>(obj.location()));                \
  }

MAKE_TO_LOCAL(ToLocal, Context, Context)
MAKE_TO_LOCAL(ToLocal, Object, Value)
MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
MAKE_TO_LOCAL(ToLocal, String, String)
MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
MAKE_TO_LOCAL(ToLocal, JSObject, Object)
MAKE_TO_LOCAL(ToLocal, JSArray, Array)
MAKE_TO_LOCAL(ToLocal, Foreign, External)
MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate)
MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate)
MAKE_TO_LOCAL(ToLocal, SignatureInfo, Signature)
MAKE_TO_LOCAL(ToLocal, TypeSwitchInfo, TypeSwitch)
MAKE_TO_LOCAL(MessageToLocal, Object, Message)
MAKE_TO_LOCAL(StackTraceToLocal, JSArray, StackTrace)
MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame)
MAKE_TO_LOCAL(NumberToLocal, Object, Number)
MAKE_TO_LOCAL(IntegerToLocal, Object, Integer)
MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32)

#undef MAKE_TO_LOCAL

  

对于v8::String 和v8::internal::String来说宏展开后就是

OpenHandle:

  v8::internal::Handle<v8::internal::String> Utils::OpenHandle(const v8::String* that) { 
    return v8::internal::Handle<v8::internal::String>( 
        reinterpret_cast<v8::internal::String**>(const_cast<v8::String*>(that))); 
  }

  

ToLocal:

  Local<v8::String> Utils::ToLocal(v8::internal::Handle<v8::internal::String> obj) { 
    ASSERT(obj.is_null() || !obj->IsTheHole());                             
    return Local<String>(reinterpret_cast<String*>(obj.location())); 
  }

  

String的构建过程(samples/Shell.cc):

OS: Win7_IA32

v8的例子程序Shell.cc中可以用load来读取一个utf8编码的js文件,返回v8::String类型。

Js文件内容为:

 

//encoding: utf8
//filename: a.js
var a="abc你好";
var b="gogogo";
function f()
{
	print(a+b);
}
function fun()
{
	print("just a test");
}

 

  

文件路径为d:\\a.js,在编译好的shell.exe中输入

load("d:\\a.js");

调用Load方法。

 

utf8编码文件构造v8::String的过程:

 

1、v8::String::New()有2个重载函数,这里调用第一个

 

	Local<String> v8::String::New(const char* data, int length);//char
	Local<String> v8::String::New(const uint16_t* data, int length);//wchar_t

 

2、v8::internal::Factory中有三种构建v8::internal::String的方法,char类型的v8::String::New()调用第二个

i::Handle<i::String> i::Factory::NewStringFromAscii(Vector<const char> string, PretenureFlag pretenure);//Ascii String
i::Handle<i::String> i::Factory::NewStringFromUtf8(Vector<const char> string, PretenureFlag pretenure);//Utf8 String
i::Handle<i::String> i::Factory::NewStringFromTwoByte(Vector<const uc16> string,PretenureFlag pretenure); //Wide String

3、i::Factory::NewStringFromUtf8()负责调用i::Heap::NewStringFromUtf8(),并将返回的i::MaybeObject*类型转换为i::Handle<i::String>类型

4、在i::Heap::NewStringFromUtf8()中先判断该字符串是否全部为ascii(c<128),全为ascii调用i::Heap::AllocateRawAsciiString(),否则调用i::Heap::AllocateStringFromUtf8Slow()。

5、全为asciii::Heap::AllocateStringFromAscii()调用i::Heap::AllocateRawAsciiString(),i::Heap::AllocateRawAsciiString()负责计算申请空间的长度,并调用i::Heap::AllocateRaw()申请空间,设置相应位后返回申请的指针;i::Heap::AllocateStringFromAscii()再调用i::SeqAsciiString::SeqAsciiStringSet()将ascii字符串复制到申请的空间里,每个字符占用1byte空间。

6、含有非ascii字符时i::Heap::AllocateStringFromUtf8Slow()调用i::Heap::AllocateRawTwoByteString(),i::Heap::AllocateRawTwoByteString()负责计算申请空间的长度,并调用i::Heap::AllocateRaw()申请空间,设置相应位后返回申请的指针;i::Heap::AllocateStringFromUtf8Slow()再调用i::String::Set()将字符串复制到申请的内存空间,所有字符均占用2byte空间。

PS. 1、申请内存大小的计算

  //全Ascii字符串:调用i::SeqAsciiString::SizeFor()计算

 //namespace v8::internal;

    

	const int kPointerSizeLog2 = 2;//32-bit
	const int kObjectAlignmentBits = kPointerSizeLog2;
	const intptr_t kObjectAlignment = 1 << kObjectAlignmentBits;
	const intptr_t kObjectAlignmentMask = kObjectAlignment - 1;
	#define OBJECT_POINTER_ALIGN(value) (((value) + kObjectAlignmentMask) & ~kObjectAlignmentMask)
	
	const int kPointerSize  = sizeof(void*);
	static const int Object::kHeaderSize = 0;
	static const int kMapOffset = Object::kHeaderSize;
	static const int HeapObject::kHeaderSize = kMapOffset + kPointerSize;
	static const int kLengthOffset = HeapObject::kHeaderSize;
	static const int kHashFieldOffset = kLengthOffset + kPointerSize;
	static const int String::kSize = kHashFieldOffset + kPointerSize;
	static const int kHeaderSize = String::kSize;
	
	const int kCharSize     = sizeof(char);//=1, win32, ia32, vc
	
	//计算长度, OBJECT_POINTER_ALIGN宏使申请内存的长度按4对齐
	static int SizeFor(int length) {//length ascii字符串长度
	    return OBJECT_POINTER_ALIGN(kHeaderSize + length * kCharSize);
	  }
	//还有非ascii时:调用i::SeqTwoByteString::SizeFor()计算
	//内存对齐和计算kHeaderSize和上面相同,不同的是每个字符要占用2bytes
	const int kShortSize    = sizeof(short);//=2, win32, ia32, vc
	static int SizeFor(int length) {
	    return OBJECT_POINTER_ALIGN(kHeaderSize + length * kShortSize);
	  }

2、对上面申请内存填充,对上面申请内存的相应部位进行填充

   分别填充map,length(Smi),hashfield.

//ascii string,非全ascii string填充方法类似
MaybeObject* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) {

     .................................................

  // Partially initialize the object.
  HeapObject::cast(result)->set_map_no_write_barrier(ascii_string_map());
  String::cast(result)->set_length(length);
  String::cast(result)->set_hash_field(String::kEmptyHashField);
  ASSERT_EQ(size, HeapObject::cast(result)->Size());
  return result;
}

 

const int kHeapObjectTag = 1;
#define FIELD_ADDR(p, offset) (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag) //?为什么要减1
#define WRITE_FIELD(p, offset, value) (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
static const int Object::kHeaderSize = 0;
static const int kMapOffset = Object::kHeaderSize;
void HeapObject::set_map_word(MapWord map_word) {
  WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));

}

void HeapObject::set_map_no_write_barrier(Map* value) {
  set_map_word(MapWord::FromMap(value));

}

//其他填充过程类似

  

 


posted @ 2012-01-19 21:20  zhangshine  阅读(1349)  评论(0编辑  收藏  举报