[草稿] [草稿帖][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: 你这太邪恶了……
Global site tag (gtag.js) - Google Analytics