This weekend I improved my prototype compiler which compiles JS to x86, using the global property jump optimization. The compiler is rather minimal and handles just enough to compile fib and similar simple code. This prototype is mainly useful to explore various implementation approaches quickly, without the burden of the complete Tachyon compiler. It allowed me to test the performance of the global property jump optimization I proposed. Two versions were tested: proto1 = optimization of global property calls keeping the argument count setup and check in all cases proto2 = optimization of global property calls without the argument count setup and check when the number of parameters matches the number of arguments The results are very good. On fib(40), proto2 generate faster code than V8 (1.5x) and SpiderMonkey (2.3x), and Tachyon (18x). There is a 1.2x difference between proto1 and proto2 (in other words, there is a 20% overhead to setup and check argument counts). Here are the detailed running times: relative time to proto2 Tachyon 29.613 (18.3) SM 3.700 ( 2.3) V8 2.397 ( 1.5) proto1 2.000 ( 1.2) proto2 1.614 ( 1.0) Please examine the x86 code generated by proto2. Note that it performs all the expected dynamic type checks, and also the stack overflow checks. The optimization in proto2 will replace the code of the global property jump: call jump_global_prop_handler # perform jump to global property .long 3 # fib .byte 1,0 # number of arguments and filler with the direct jump: jmp fib_7 The details are in the attached file. If you have any questions please let me know. Here's a question for Maxime and Erick... can you estimate the work needed to get Tachyon to generate similar x86 code? Marc # notes: # # %ecx = context register # %eax = argument 1 of function and return value of function # %edi = return address # %ebp = stack pointer # # function fib(x) # { # if (x < 2) # return x; # else # return fib(x-1) + fib(x-2); # } fib_7: # main entry point of "fib" subb $1,%cl # check that arg_count = 1 jne _13 _14: testb $3,%al # check that x is a fixnum jne _17 cmpl $8,%eax # compare it to 2 jge else_16 then_15: jmp *%edi # return x (which is already in %eax) when x<2 _13: addb $1,%cl # handle arg_count != param_count pushl %ecx xorb %cl,%cl call *16(%ecx) jmp _14 _17: pushl %eax # handle generic "x < 2" pushl $8 call *28(%ecx) jl then_15 jmp else_16 else_16: movl %eax,-4(%ebp) # save x for later testb $3,%al # check that x is a fixnum jne _19 subl $8,%eax # "x - 2" jo _20 # check for overflow _21: # no overflow movl %edi,-8(%ebp) # save return address on stack addl $-8,%ebp # allocate frame on stack cmpl %ebp,(%ecx) # check for stack overflow ja _22 _23: # jump to global property "fib" movl $_18,%edi # setup return address movl 4(%ecx),%esi # setup "this" argument (= global object) call jump_global_prop_handler # perform jump to global property .long 3 # fib .byte 1,0 # number of arguments and filler _20: addl $8,%eax # undo subtraction that overflowed _19: pushl %eax # handle generic "x - 2" pushl $8 call *28(%ecx) jmp _21 _22: call *12(%ecx) # handle stack overflow jmp _23 ALIGN_RET_POINT FRAME_DESCR .long RET_POINT_TYPE RET_POINT_HEADER_END _18: # return point of call fib(x-2) movl 4(%ebp),%ebx # get x testb $3,%bl # check that x is a fixnum jne _25 subl $4,%ebx # "x - 1" jo _26 # check for overflow _27: movl %eax,-4(%ebp) # save result of call fib(x-2) movl %ebx,%eax # prepare argument of call fib(x-1) addl $-4,%ebp # grow frame on stack cmpl %ebp,(%ecx) # check for stack overflow ja _28 _29: # jump to global property "fib" movl $_24,%edi # setup return address movl 4(%ecx),%esi # setup "this" argument (= global object) call jump_global_prop_handler # perform jump to global property .long 3 # fib .byte 1,0 # number of arguments and filler _26: addl $4,%ebx # undo subtraction that overflowed _25: pushl %ebx # handle generic "x - 1" pushl $4 call *28(%ecx) jmp _27 _28: call *12(%ecx) # handle stack overflow jmp _29 ALIGN_RET_POINT FRAME_DESCR .long RET_POINT_TYPE RET_POINT_HEADER_END _24: # return point of call fib(x-1) testb $3,%al # check that result of call fib(x-1) is a fixnum jne _30 testb $3,(%ebp) # check that result of call fib(x-2) is a fixnum jne _30 addl (%ebp),%eax # add result of calls fib(x-1) and fib(x-2) jo _31 # check for overflow _32: addl $12,%ebp # remove stack frame jmp *-8(%ebp) # jump to return address _31: subl (%ebp),%eax # undo addition that overflowed _30: pushl %eax # handle generic "fib(x-1) + fib(x-2)" pushl -12(%ebp) call *28(%ecx) jmp _32