[草稿] [草稿帖][2009-08-21][JavaScript][V8][Nitro] 响应号召,放一个V8/Nitro相关的草稿出来
RednaxelaFX
2010-02-18
这种资料堆在草稿箱里久了必烂……先放一篇出来吧。这篇是去年8月记的。总之就是草稿,pre-alpha质量。
JavaScriptCore SquirrelFish -> 它的bytecode spec SquirrelFish Extreme(简称SFX) 后将SFX改名为Nitro Google V8 http://code.google.com/p/v8/ V8有JIT,SFX也有。V8是直接从AST生成native code,SFX是从字节码通过context-threading的方式来生成native code。 (peephole优化在context-threading里应该可以通过super-instruction和对应的handler来实现?<< 要调查) V8中在parse过程中就进行了自底向上的常量折叠。尽量把多的功能塞到一趟(pass)里来提高效率。代价是不同作用的代码给混在一起了。 V8的hidden classes机制,SFX也有。刚开始叫做StructureID,后来应该是改名为就是Structure/StructureChain等类了。 V8的inline cache是monomorphic inline cache->megamorphic inline cache,SFX的似乎是polymorphic inline cache(<< 要调查) V8的GC是分2代的准确式GC,年轻代有copying(有from space和to space),年老代有mark-and-sweep和mark-and-compact。有用到semi space。用remember set来记录年老到年轻对象的引用。C++代码要引用GC堆上的对象需要通过Handle。heap.cc:Heap::CollectGarbage()看来是GC收集的入口函数,而Heap::PerformGarbageCollection()是其中的核心。贯穿这些函数,GCTracer会收集GC效率的信息,用来指导下次GC采取的策略。 SFX的GC看来在栈上是保守的……嗯?多线程时也保守。stop-the-world,无分代的mark-and-sweep? SFX中: runtime/collector.cpp Heap::markConservatively 看来有保守GC的部分(<< 要调查) runtime/collector.cpp Heap::markCurrentThreadConservatively << 用到了setjmp()来获取寄存器内容(保存到局部变量jmp_buf registers里) runtime/collector.cpp bool Heap::collect() { // snipped... JAVASCRIPTCORE_GC_BEGIN(); primaryHeap.operationInProgress = Collection; numberHeap.operationInProgress = Collection; // MARK: first mark all referenced objects recursively starting out from the set of root objects MarkStack& markStack = m_globalData->markStack; markStackObjectsConservatively(markStack); markProtectedObjects(markStack); if (m_markListSet && m_markListSet->size()) MarkedArgumentBuffer::markLists(markStack, *m_markListSet); if (m_globalData->exception && !m_globalData->exception.marked()) markStack.append(m_globalData->exception); m_globalData->interpreter->registerFile().markCallFrames(markStack, this); m_globalData->smallStrings.mark(); if (m_globalData->functionCodeBlockBeingReparsed) m_globalData->functionCodeBlockBeingReparsed->markAggregate(markStack); if (m_globalData->firstStringifierToMark) JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark); markStack.drain(); markStack.compact(); JAVASCRIPTCORE_GC_MARKED(); // snipped... } wtf/RefCounted.h // This base class holds the non-template methods and attributes. // The RefCounted class inherits from it reducing the template bloat // generated by the compiler (technique called template hoisting). class RefCountedBase { JavaScriptCore以前用的正则表达式引擎叫JSCRE,是Webkit计划从PCRE分支出来的。V8刚开始也是使用该引擎。后来V8自行开发了Irregexp,通过JIT来生成正则表达式对应的自动机的native code;Webkit也开发了WREC(WebKit Regular Expression Compiler)应用在SFX中,同样是通过JIT来生成更高效的处理代码。 V8的String的内部表现是用UC16编码(<< UC16是啥?UTF-16么?) 在Windows上,V8的OS::Allocate()里会调用VirtualAlloc(),因为 1、V8的JIT生成的代码是通过这个函数得到空间的,而它必须在可执行的页上,必须用VirtualAlloc() 2、VirtualAlloc()会自动round到4K边界上,占用完整的pages。 V8的snapshot机制,http://groups.google.com/group/v8-users/browse_thread/thread/890aff07aded7fee Compile v8 code, save in binary file and after then run stand alone or in c++ application. function foo() { return 1 + 2; } --- Code --- kind = FUNCTION name = foo Instructions (size = 38) 02E32FC0 0 55 push ebp 02E32FC1 1 8bec mov ebp,esp 02E32FC3 3 56 push esi 02E32FC4 4 57 push edi 02E32FC5 5 3b25400d7400 cmp esp,[0x740d40] 02E32FCB 11 0f820b000000 jc 28 (02E32FDC) 02E32FD1 17 b806000000 mov eax,00000006 ;; debug: statement 17 02E32FD6 22 8be5 mov esp,ebp ;; js return 02E32FD8 24 5d pop ebp 02E32FD9 25 c20400 ret 0x4 02E32FDC 28 e8bfd4feff call 02E204A0 ;; debug: statement 12 ;; code: STUB, StackCheck, minor: 0 02E32FE1 33 8b7df8 mov edi,[ebp+0xf8] 02E32FE4 36 ebeb jmp 17 (02E32FD1) RelocInfo (size = 7) 02E32FD1 statement position (17) 02E32FD6 js return 02E32FDC statement position (12) 02E32FDD code target (STUB) (02E204A0) 这个函数除了prologue和epilogue之外,只有一句关键指令,mov eax,00000006。这个6是1+2常量折叠为3然后按照V8的tagged pointer格式左移一位得到的。换句话说foo()的实体就变成了一句简单的return 3。 D:\sdk\V8>shell_g.exe --print_code --shell V8 version 2.0.0 > function foo() { return 1 + 2; } --- Raw source --- function foo() { return 1 + 2; } --- Code --- kind = FUNCTION Instructions (size = 46) 02E32EA0 0 55 push ebp 02E32EA1 1 89e5 mov ebp,esp 02E32EA3 3 56 push esi 02E32EA4 4 57 push edi 02E32EA5 5 56 push esi 02E32EA6 6 680d2d3f00 push 0x3f2d0d ;; object: 003F2D0D <FixedArray[2]> 02E32EAB 11 6a00 push 0x0 02E32EAD 13 e86e01ffff call 02E23020 ;; debug: statement 0 ;; code: STUB, Runtime, RuntimeStub_DeclareGlobals 02E32EB2 18 3b25400d7400 cmp esp,[0x740d40] 02E32EB8 24 0f8305000000 jnc 35 (02E32EC3) 02E32EBE 30 e8ddd5feff call 02E204A0 ;; code: STUB, StackCheck, minor: 0 02E32EC3 35 b82901e002 mov eax,02E00129 ;; object: 02E00129 <undefined> 02E32EC8 40 89ec mov esp,ebp ;; debug: statement 33 ;; js return 02E32ECA 42 5d pop ebp 02E32ECB 43 c20400 ret 0x4 RelocInfo (size = 10) 02E32EA7 embedded object (003F2D0D <FixedArray[2]>) 02E32EAD statement position (0) 02E32EAE code target (STUB) (02E23020) 02E32EBF code target (STUB) (02E204A0) 02E32EC4 embedded object (02E00129 <undefined>) 02E32EC8 statement position (33) 02E32EC8 js return > foo() --- Raw source --- foo() --- Code --- kind = FUNCTION Instructions (size = 65) 02E32F20 0 55 push ebp 02E32F21 1 89e5 mov ebp,esp 02E32F23 3 56 push esi 02E32F24 4 57 push edi 02E32F25 5 682901e002 push 0x2e00129 ;; object: 02E00129 <undefined> 02E32F2A 10 3b25400d7400 cmp esp,[0x740d40] 02E32F30 16 0f8305000000 jnc 27 (02E32F3B) 02E32F36 22 e865d5feff call 02E204A0 ;; debug: statement 0 ;; code: STUB, StackCheck, minor: 0 02E32F3B 27 685134e002 push 0x2e03451 ;; object: 02E03451 <String[3]: foo> 02E32F40 32 ff7617 push [esi+0x17] 02E32F43 35 e8181effff call 02E24D60 ;; code: contextual, CALL_IC, UNINITIALIZED, argc = 0 02E32F48 40 8b75fc mov esi,[ebp+0xfc] 02E32F4B 43 890424 mov [esp],eax 02E32F4E 46 8f45f4 pop [ebp+0xf4] 02E32F51 49 8b45f4 mov eax,[ebp+0xf4] 02E32F54 52 89ec mov esp,ebp ;; js return 02E32F56 54 5d pop ebp 02E32F57 55 c20400 ret 0x4 02E32F5A 58 b82901e002 mov eax,02E00129 ;; object: 02E00129 <undefined> 02E32F5F 63 ebf3 jmp 52 (02E32F54) RelocInfo (size = 10) 02E32F26 embedded object (02E00129 <undefined>) 02E32F36 statement position (0) 02E32F37 code target (STUB) (02E204A0) 02E32F3C embedded object (02E03451 <String[3]: foo>) 02E32F44 code target (context) (CALL_IC) (02E24D60) 02E32F54 js return 02E32F5B embedded object (02E00129 <undefined>) --- Raw source --- () { return 1 + 2; } --- Code --- kind = FUNCTION name = foo Instructions (size = 38) 02E32FC0 0 55 push ebp 02E32FC1 1 8bec mov ebp,esp 02E32FC3 3 56 push esi 02E32FC4 4 57 push edi 02E32FC5 5 3b25400d7400 cmp esp,[0x740d40] 02E32FCB 11 0f820b000000 jc 28 (02E32FDC) 02E32FD1 17 b806000000 mov eax,00000006 ;; debug: statement 17 02E32FD6 22 8be5 mov esp,ebp ;; js return 02E32FD8 24 5d pop ebp 02E32FD9 25 c20400 ret 0x4 02E32FDC 28 e8bfd4feff call 02E204A0 ;; debug: statement 12 ;; code: STUB, StackCheck, minor: 0 02E32FE1 33 8b7df8 mov edi,[ebp+0xf8] 02E32FE4 36 ebeb jmp 17 (02E32FD1) RelocInfo (size = 7) 02E32FD1 statement position (17) 02E32FD6 js return 02E32FDC statement position (12) 02E32FDD code target (STUB) (02E204A0) 3 > quit() --- Raw source --- quit() --- Code --- kind = FUNCTION Instructions (size = 65) 02E33040 0 55 push ebp 02E33041 1 89e5 mov ebp,esp 02E33043 3 56 push esi 02E33044 4 57 push edi 02E33045 5 682901e002 push 0x2e00129 ;; object: 02E00129 <undefined> 02E3304A 10 3b25400d7400 cmp esp,[0x740d40] 02E33050 16 0f8305000000 jnc 27 (02E3305B) 02E33056 22 e845d4feff call 02E204A0 ;; debug: statement 0 ;; code: STUB, StackCheck, minor: 0 02E3305B 27 682933e002 push 0x2e03329 ;; object: 02E03329 <String[4]: quit> 02E33060 32 ff7617 push [esi+0x17] 02E33063 35 e8f81cffff call 02E24D60 ;; code: contextual, CALL_IC, UNINITIALIZED, argc = 0 02E33068 40 8b75fc mov esi,[ebp+0xfc] 02E3306B 43 890424 mov [esp],eax 02E3306E 46 8f45f4 pop [ebp+0xf4] 02E33071 49 8b45f4 mov eax,[ebp+0xf4] 02E33074 52 89ec mov esp,ebp ;; js return 02E33076 54 5d pop ebp 02E33077 55 c20400 ret 0x4 02E3307A 58 b82901e002 mov eax,02E00129 ;; object: 02E00129 <undefined> 02E3307F 63 ebf3 jmp 52 (02E33074) RelocInfo (size = 10) 02E33046 embedded object (02E00129 <undefined>) 02E33056 statement position (0) 02E33057 code target (STUB) (02E204A0) 02E3305C embedded object (02E03329 <String[4]: quit>) 02E33064 code target (context) (CALL_IC) (02E24D60) 02E33074 js return 02E3307B embedded object (02E00129 <undefined>) --- Raw source --- (a){ if(%_IsSmi(a))return a; return %NumberToJSInt32(ToNumber(a)); } --- Code --- kind = FUNCTION name = ToInt32 Instructions (size = 72) 02E33120 0 55 push ebp 02E33121 1 8bec mov ebp,esp 02E33123 3 56 push esi 02E33124 4 57 push edi 02E33125 5 3b25400d7400 cmp esp,[0x740d40] 02E3312B 11 0f822d000000 jc 62 (02E3315E) 02E33131 17 8b4508 mov eax,[ebp+0x8] 02E33134 20 a801 test al,0x1 02E33136 22 0f8506000000 jnz 34 (02E33142) 02E3313C 28 8be5 mov esp,ebp ;; debug: statement 8356 ;; js return 02E3313E 30 5d pop ebp 02E3313F 31 c20800 ret 0x8 02E33142 34 8b5e17 mov ebx,[esi+0x17] 02E33145 37 682902e002 push 0x2e00229 ;; object: 02E00229 <String[8]: ToNumber> 02E3314A 42 53 push ebx 02E3314B 43 50 push eax 02E3314C 44 e86fe2feff call 02E213C0 ;; debug: statement 8366 ;; debug: position 8390 ;; code: contextual, CALL_IC, UNINITIALIZED, in_loop, argc = 1 02E33151 49 8b75fc mov esi,[ebp+0xfc] 02E33154 52 8945f4 mov [ebp+0xf4],eax 02E33157 55 e884ffffff call 02E330E0 ;; code: STUB, Runtime, RuntimeStub_NumberToJSInt32 02E3315C 60 ebde jmp 28 (02E3313C) 02E3315E 62 e83dd3feff call 02E204A0 ;; debug: statement 8337 ;; code: STUB, StackCheck, minor: 0 02E33163 67 8b7df8 mov edi,[ebp+0xf8] 02E33166 70 ebc9 jmp 17 (02E33131) RelocInfo (size = 20) 02E3313C statement position (8356) 02E3313C js return 02E33146 embedded object (02E00229 <String[8]: ToNumber>) 02E3314C statement position (8366) 02E3314C position (8390) 02E3314D code target (context) (CALL_IC) (02E213C0) 02E33158 code target (STUB) (02E330E0) 02E3315E statement position (8337) 02E3315F code target (STUB) (02E204A0) << 完整session的记录 native codegen是lazy的:函数调用一开始只是stub,目标被调用时才被编译 |
|
RednaxelaFX
2010-02-18
JavaEye的圈子论坛的样式有点怪……
上面内容看不全的同学,如果是用FireFox的话: 打开FireBug,在HTML那栏里把div#main里的overflow:hidden;去掉 << 这样就能看到右侧切掉的内容了。 其它浏览器的用户请用相应的办法把overflow:hidden;去掉。 |
|
lurker0
2010-02-18
其实复制代码到记事本,也是可以看全的。
要是样式能自动换行就好了。 |
|
RednaxelaFX
2010-02-19
lurker0 写道 其实复制代码到记事本,也是可以看全的。
要是样式能自动换行就好了。 这里的样式本来就是有自动换行的,但是因为div的实际宽度比可见宽度大,所以即便有自动换行,右边还是有一部分被切掉了——至少在FireFox上看是这样的。 而且坏就坏在不只是代码被切,正文的其它部分也一起被切了 =__,=||| |
|
fantasybei
2010-02-19
-_-!!,完全看不懂的飘过..
|
|
night_stalker
2010-02-19
这个 bug 可以用来放不和谐物,hehehe FX: 你这太邪恶了…… |