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、全为ascii时i::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));
}
//其他填充过程类似



浙公网安备 33010602011771号