Backed out changeset 95b210c2fc92 preemptively. Seems to crash the browser.
authorAndreas Gal <gal@mozilla.com>
Wed, 17 Dec 2008 23:09:26 -0800
changeset 23089 29d88d7860177b3e0a31257c24006eae2b969a6c
parent 23086 95b210c2fc920a0987653dbd5229f30b8cb2af4c
child 23090 59d774acdd37a9bda4e380dbe921d2b3ef450a6d
push id4346
push userrsayre@mozilla.com
push dateFri, 26 Dec 2008 01:26:36 +0000
treeherdermozilla-central@8eb5a5b83a93 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.2a1pre
backs out95b210c2fc920a0987653dbd5229f30b8cb2af4c
Backed out changeset 95b210c2fc92 preemptively. Seems to crash the browser.
js/src/imacro_asm.js.in
js/src/imacros.c.out
js/src/imacros.jsasm
js/src/jsinterp.cpp
js/src/jsopcode.tbl
js/src/jstracer.cpp
js/src/jstracer.h
js/src/trace-test.js
--- a/js/src/imacro_asm.js.in
+++ b/js/src/imacro_asm.js.in
@@ -100,18 +100,16 @@ function immediate(op) {
     let info = op.info;
     if (info.flags.indexOf("JOF_ATOM") >= 0) {
         if (/^(?:void|object|function|string|number|boolean)$/.test(op.imm1))
             return "0, COMMON_TYPE_ATOM_INDEX(JSTYPE_" + op.imm1.toUpperCase() + ")";
         return "0, COMMON_ATOM_INDEX(" + op.imm1 + ")";
     }
     if (info.flags.indexOf("JOF_JUMP") >= 0)
         return ((op.target >> 8) & 0xff) + ", " + (op.target & 0xff);
-    if (info.flags.indexOf("JOF_UINT8") >= 0)
-        return (op.imm1 & 0xff);
     if (info.flags.indexOf("JOF_UINT16") >= 0)
         return ((op.imm1 & 0xff00) >> 8) + ", " + (op.imm1 & 0xff);
     throw new Error(info.jsop + " format not yet implemented");
 }
 
 /*
  * Syntax (spaces are significant only to delimit tokens):
  *
--- a/js/src/imacros.c.out
+++ b/js/src/imacros.c.out
@@ -166,299 +166,16 @@ static struct {
 /*62*/  JSOP_CALL, 0, 0,
 /*65*/  JSOP_GOTO, 0, 5,
 /*68*/  JSOP_SWAP,
 /*69*/  JSOP_POP,
 /*70*/  JSOP_ADD,
 /*71*/  JSOP_STOP,
     },
 };
-static struct {
-    jsbytecode apply0[8];
-    jsbytecode apply1[12];
-    jsbytecode apply2[16];
-    jsbytecode apply3[21];
-    jsbytecode apply4[26];
-    jsbytecode apply5[31];
-    jsbytecode apply6[36];
-    jsbytecode apply7[41];
-    jsbytecode apply8[46];
-    jsbytecode call0[7];
-    jsbytecode call1[7];
-    jsbytecode call2[7];
-    jsbytecode call3[7];
-    jsbytecode call4[7];
-    jsbytecode call5[7];
-    jsbytecode call6[7];
-    jsbytecode call7[7];
-    jsbytecode call8[7];
-} apply_imacros = {
-    {
-/* 0*/  JSOP_PICK, 3,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_POP,
-/* 4*/  JSOP_CALL, 0, 0,
-/* 7*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_PICK, 3,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_DUP,
-/* 4*/  JSOP_ZERO,
-/* 5*/  JSOP_GETELEM,
-/* 6*/  JSOP_SWAP,
-/* 7*/  JSOP_POP,
-/* 8*/  JSOP_CALL, 0, 1,
-/*11*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_PICK, 3,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_DUP,
-/* 4*/  JSOP_ZERO,
-/* 5*/  JSOP_GETELEM,
-/* 6*/  JSOP_SWAP,
-/* 7*/  JSOP_DUP,
-/* 8*/  JSOP_ONE,
-/* 9*/  JSOP_GETELEM,
-/*10*/  JSOP_SWAP,
-/*11*/  JSOP_POP,
-/*12*/  JSOP_CALL, 0, 2,
-/*15*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_PICK, 3,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_DUP,
-/* 4*/  JSOP_ZERO,
-/* 5*/  JSOP_GETELEM,
-/* 6*/  JSOP_SWAP,
-/* 7*/  JSOP_DUP,
-/* 8*/  JSOP_ONE,
-/* 9*/  JSOP_GETELEM,
-/*10*/  JSOP_SWAP,
-/*11*/  JSOP_DUP,
-/*12*/  JSOP_INT8, 2,
-/*14*/  JSOP_GETELEM,
-/*15*/  JSOP_SWAP,
-/*16*/  JSOP_POP,
-/*17*/  JSOP_CALL, 0, 3,
-/*20*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_PICK, 3,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_DUP,
-/* 4*/  JSOP_ZERO,
-/* 5*/  JSOP_GETELEM,
-/* 6*/  JSOP_SWAP,
-/* 7*/  JSOP_DUP,
-/* 8*/  JSOP_ONE,
-/* 9*/  JSOP_GETELEM,
-/*10*/  JSOP_SWAP,
-/*11*/  JSOP_DUP,
-/*12*/  JSOP_INT8, 2,
-/*14*/  JSOP_GETELEM,
-/*15*/  JSOP_SWAP,
-/*16*/  JSOP_DUP,
-/*17*/  JSOP_INT8, 3,
-/*19*/  JSOP_GETELEM,
-/*20*/  JSOP_SWAP,
-/*21*/  JSOP_POP,
-/*22*/  JSOP_CALL, 0, 4,
-/*25*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_PICK, 3,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_DUP,
-/* 4*/  JSOP_ZERO,
-/* 5*/  JSOP_GETELEM,
-/* 6*/  JSOP_SWAP,
-/* 7*/  JSOP_DUP,
-/* 8*/  JSOP_ONE,
-/* 9*/  JSOP_GETELEM,
-/*10*/  JSOP_SWAP,
-/*11*/  JSOP_DUP,
-/*12*/  JSOP_INT8, 2,
-/*14*/  JSOP_GETELEM,
-/*15*/  JSOP_SWAP,
-/*16*/  JSOP_DUP,
-/*17*/  JSOP_INT8, 3,
-/*19*/  JSOP_GETELEM,
-/*20*/  JSOP_SWAP,
-/*21*/  JSOP_DUP,
-/*22*/  JSOP_INT8, 4,
-/*24*/  JSOP_GETELEM,
-/*25*/  JSOP_SWAP,
-/*26*/  JSOP_POP,
-/*27*/  JSOP_CALL, 0, 5,
-/*30*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_PICK, 3,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_DUP,
-/* 4*/  JSOP_ZERO,
-/* 5*/  JSOP_GETELEM,
-/* 6*/  JSOP_SWAP,
-/* 7*/  JSOP_DUP,
-/* 8*/  JSOP_ONE,
-/* 9*/  JSOP_GETELEM,
-/*10*/  JSOP_SWAP,
-/*11*/  JSOP_DUP,
-/*12*/  JSOP_INT8, 2,
-/*14*/  JSOP_GETELEM,
-/*15*/  JSOP_SWAP,
-/*16*/  JSOP_DUP,
-/*17*/  JSOP_INT8, 3,
-/*19*/  JSOP_GETELEM,
-/*20*/  JSOP_SWAP,
-/*21*/  JSOP_DUP,
-/*22*/  JSOP_INT8, 4,
-/*24*/  JSOP_GETELEM,
-/*25*/  JSOP_SWAP,
-/*26*/  JSOP_DUP,
-/*27*/  JSOP_INT8, 5,
-/*29*/  JSOP_GETELEM,
-/*30*/  JSOP_SWAP,
-/*31*/  JSOP_POP,
-/*32*/  JSOP_CALL, 0, 6,
-/*35*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_PICK, 3,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_DUP,
-/* 4*/  JSOP_ZERO,
-/* 5*/  JSOP_GETELEM,
-/* 6*/  JSOP_SWAP,
-/* 7*/  JSOP_DUP,
-/* 8*/  JSOP_ONE,
-/* 9*/  JSOP_GETELEM,
-/*10*/  JSOP_SWAP,
-/*11*/  JSOP_DUP,
-/*12*/  JSOP_INT8, 2,
-/*14*/  JSOP_GETELEM,
-/*15*/  JSOP_SWAP,
-/*16*/  JSOP_DUP,
-/*17*/  JSOP_INT8, 3,
-/*19*/  JSOP_GETELEM,
-/*20*/  JSOP_SWAP,
-/*21*/  JSOP_DUP,
-/*22*/  JSOP_INT8, 4,
-/*24*/  JSOP_GETELEM,
-/*25*/  JSOP_SWAP,
-/*26*/  JSOP_DUP,
-/*27*/  JSOP_INT8, 5,
-/*29*/  JSOP_GETELEM,
-/*30*/  JSOP_SWAP,
-/*31*/  JSOP_DUP,
-/*32*/  JSOP_INT8, 6,
-/*34*/  JSOP_GETELEM,
-/*35*/  JSOP_SWAP,
-/*36*/  JSOP_POP,
-/*37*/  JSOP_CALL, 0, 7,
-/*40*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_PICK, 3,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_DUP,
-/* 4*/  JSOP_ZERO,
-/* 5*/  JSOP_GETELEM,
-/* 6*/  JSOP_SWAP,
-/* 7*/  JSOP_DUP,
-/* 8*/  JSOP_ONE,
-/* 9*/  JSOP_GETELEM,
-/*10*/  JSOP_SWAP,
-/*11*/  JSOP_DUP,
-/*12*/  JSOP_INT8, 2,
-/*14*/  JSOP_GETELEM,
-/*15*/  JSOP_SWAP,
-/*16*/  JSOP_DUP,
-/*17*/  JSOP_INT8, 3,
-/*19*/  JSOP_GETELEM,
-/*20*/  JSOP_SWAP,
-/*21*/  JSOP_DUP,
-/*22*/  JSOP_INT8, 4,
-/*24*/  JSOP_GETELEM,
-/*25*/  JSOP_SWAP,
-/*26*/  JSOP_DUP,
-/*27*/  JSOP_INT8, 5,
-/*29*/  JSOP_GETELEM,
-/*30*/  JSOP_SWAP,
-/*31*/  JSOP_DUP,
-/*32*/  JSOP_INT8, 6,
-/*34*/  JSOP_GETELEM,
-/*35*/  JSOP_SWAP,
-/*36*/  JSOP_DUP,
-/*37*/  JSOP_INT8, 7,
-/*39*/  JSOP_GETELEM,
-/*40*/  JSOP_SWAP,
-/*41*/  JSOP_POP,
-/*42*/  JSOP_CALL, 0, 8,
-/*45*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_SWAP,
-/* 1*/  JSOP_POP,
-/* 2*/  JSOP_NULLTHIS,
-/* 3*/  JSOP_CALL, 0, 0,
-/* 6*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_PICK, 2,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_CALL, 0, 0,
-/* 6*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_PICK, 3,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_CALL, 0, 1,
-/* 6*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_PICK, 4,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_CALL, 0, 2,
-/* 6*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_PICK, 5,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_CALL, 0, 3,
-/* 6*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_PICK, 6,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_CALL, 0, 4,
-/* 6*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_PICK, 7,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_CALL, 0, 5,
-/* 6*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_PICK, 8,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_CALL, 0, 6,
-/* 6*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_PICK, 9,
-/* 2*/  JSOP_POP,
-/* 3*/  JSOP_CALL, 0, 7,
-/* 6*/  JSOP_STOP,
-    },
-};
 uint8 js_opcode2extra[JSOP_LIMIT] = {
     0,  /* JSOP_INTERRUPT */
     0,  /* JSOP_PUSH */
     0,  /* JSOP_POPV */
     0,  /* JSOP_ENTERWITH */
     0,  /* JSOP_LEAVEWITH */
     0,  /* JSOP_RETURN */
     0,  /* JSOP_GOTO */
@@ -528,17 +245,17 @@ uint8 js_opcode2extra[JSOP_LIMIT] = {
     0,  /* JSOP_TABLESWITCH */
     0,  /* JSOP_LOOKUPSWITCH */
     0,  /* JSOP_STRICTEQ */
     0,  /* JSOP_STRICTNE */
     0,  /* JSOP_NULLTHIS */
     0,  /* JSOP_ITER */
     0,  /* JSOP_NEXTITER */
     0,  /* JSOP_ENDITER */
-    7,  /* JSOP_APPLY */
+    0,  /* JSOP_APPLY */
     0,  /* JSOP_SWAP */
     0,  /* JSOP_OBJECT */
     0,  /* JSOP_POP */
     0,  /* JSOP_POS */
     0,  /* JSOP_TRAP */
     0,  /* JSOP_GETARG */
     0,  /* JSOP_SETARG */
     0,  /* JSOP_GETLOCAL */
@@ -651,17 +368,17 @@ uint8 js_opcode2extra[JSOP_LIMIT] = {
     0,  /* JSOP_STARTXMLEXPR */
     0,  /* JSOP_CALLELEM */
     0,  /* JSOP_STOP */
     0,  /* JSOP_GETXPROP */
     0,  /* JSOP_CALLXMLNAME */
     0,  /* JSOP_TYPEOFEXPR */
     0,  /* JSOP_ENTERBLOCK */
     0,  /* JSOP_LEAVEBLOCK */
-    0,  /* JSOP_PICK */
+    0,  /* JSOP_UNUSED201 */
     0,  /* JSOP_UNUSED202 */
     0,  /* JSOP_UNUSED203 */
     0,  /* JSOP_UNUSED204 */
     0,  /* JSOP_UNUSED205 */
     0,  /* JSOP_UNUSED206 */
     0,  /* JSOP_UNUSED207 */
     0,  /* JSOP_UNUSED208 */
     0,  /* JSOP_UNUSED209 */
--- a/js/src/imacros.jsasm
+++ b/js/src/imacros.jsasm
@@ -203,291 +203,8 @@ 6:      pop                             
         goto 8                          # lval rval
 7:      swap                            # lval rval obj
         pop                             # lval rval
 8:      add                             # aval
         stop
     .end
 
 .end
-
-.igroup apply JSOP_APPLY
-    .imacro apply0                          # apply fun this arr
-        pick 3                              # fun this arr apply
-        pop                                 # fun this arr
-        pop                                 # fun this
-        call 0                              #
-        stop                                #
-    .end                                    #
-
-    .imacro apply1                          # apply fun this arr
-        pick 3                              # fun this arr apply
-        pop                                 # fun this arr
-        dup                                 # fun this arr arr
-        zero                                # fun this arr arr 0
-        getelem                             # fun this arr arg0
-        swap                                # fun this arg0 arr
-        pop                                 # fun this arg0
-        call 1                              #
-        stop                                #
-    .end                                    #
-
-    .imacro apply2                          # apply fun this arr
-        pick 3                              # fun this arr apply
-        pop                                 # fun this arr
-        dup                                 # fun this arr arr
-        zero                                # fun this arr arr 0
-        getelem                             # fun this arr arg0
-        swap                                # fun this arg0 arr
-        dup                                 # fun this arg0 arr arr
-        one                                 # fun this arg0 arr arr 1
-        getelem                             # fun this arg0 arr arg1
-        swap                                # fun this arg0 arg1 arr
-        pop                                 # fun this arg0 arg1
-        call 2                              #
-        stop                                #
-    .end                                    #
-
-    .imacro apply3                          # apply fun this arr
-        pick 3                              # fun this arr apply
-        pop                                 # fun this arr
-        dup                                 # fun this arr arr
-        zero                                # fun this arr arr 0
-        getelem                             # fun this arr arg0
-        swap                                # fun this arg0 arr
-        dup                                 # fun this arg0 arr arr
-        one                                 # fun this arg0 arr arr 1
-        getelem                             # fun this arg0 arr arg1
-        swap                                # fun this arg0 arg1 arr
-        dup                                 # fun this arg0 arg1 arr arr
-        int8 2                              # fun this arg0 arg1 arr arr 2
-        getelem                             # fun this arg0 arg1 arr arg2
-        swap                                # fun this arg0 arg1 arg2 arr
-        pop                                 # fun this arg0 arg1 arg2
-        call 3                              #
-        stop                                #
-    .end                                    #
-
-    .imacro apply4                          # apply fun this arr
-        pick 3                              # fun this arr apply
-        pop                                 # fun this arr
-        dup                                 # fun this arr arr
-        zero                                # fun this arr arr 0
-        getelem                             # fun this arr arg0
-        swap                                # fun this arg0 arr
-        dup                                 # fun this arg0 arr arr
-        one                                 # fun this arg0 arr arr 1
-        getelem                             # fun this arg0 arr arg1
-        swap                                # fun this arg0 arg1 arr
-        dup                                 # fun this arg0 arg1 arr arr
-        int8 2                              # fun this arg0 arg1 arr arr 2
-        getelem                             # fun this arg0 arg1 arr arg2
-        swap                                # fun this arg0 arg1 arg2 arr
-        dup                                 # fun this arg0 arg1 arg2 arr arr
-        int8 3                              # fun this arg0 arg1 arg2 arr arr 3
-        getelem                             # fun this arg0 arg1 arg2 arr arg3
-        swap                                # fun this arg0 arg1 arg2 arg3 arr
-        pop                                 # fun this arg0 arg1 arg2 arg3
-        call 4                              #
-        stop                                #
-    .end                                    #
-
-    .imacro apply5                          # apply fun this arr
-        pick 3                              # fun this arr apply
-        pop                                 # fun this arr
-        dup                                 # fun this arr arr
-        zero                                # fun this arr arr 0
-        getelem                             # fun this arr arg0
-        swap                                # fun this arg0 arr
-        dup                                 # fun this arg0 arr arr
-        one                                 # fun this arg0 arr arr 1
-        getelem                             # fun this arg0 arr arg1
-        swap                                # fun this arg0 arg1 arr
-        dup                                 # fun this arg0 arg1 arr arr
-        int8 2                              # fun this arg0 arg1 arr arr 2
-        getelem                             # fun this arg0 arg1 arr arg2
-        swap                                # fun this arg0 arg1 arg2 arr
-        dup                                 # fun this arg0 arg1 arg2 arr arr
-        int8 3                              # fun this arg0 arg1 arg2 arr arr 3
-        getelem                             # fun this arg0 arg1 arg2 arr arg3
-        swap                                # fun this arg0 arg1 arg2 arg3 arr
-        dup                                 # fun this arg0 arg1 arg2 arg3 arr arr
-        int8 4                              # fun this arg0 arg1 arg2 arg3 arr arr 4
-        getelem                             # fun this arg0 arg1 arg2 arg3 arr arg4
-        swap                                # fun this arg0 arg1 arg2 arg3 arg4 arr
-        pop                                 # fun this arg0 arg1 arg2 arg3 arg4
-        call 5                              #
-        stop                                #
-    .end                                    #
-
-    .imacro apply6                          # apply fun this arr
-        pick 3                              # fun this arr apply
-        pop                                 # fun this arr
-        dup                                 # fun this arr arr
-        zero                                # fun this arr arr 0
-        getelem                             # fun this arr arg0
-        swap                                # fun this arg0 arr
-        dup                                 # fun this arg0 arr arr
-        one                                 # fun this arg0 arr arr 1
-        getelem                             # fun this arg0 arr arg1
-        swap                                # fun this arg0 arg1 arr
-        dup                                 # fun this arg0 arg1 arr arr
-        int8 2                              # fun this arg0 arg1 arr arr 2
-        getelem                             # fun this arg0 arg1 arr arg2
-        swap                                # fun this arg0 arg1 arg2 arr
-        dup                                 # fun this arg0 arg1 arg2 arr arr
-        int8 3                              # fun this arg0 arg1 arg2 arr arr 3
-        getelem                             # fun this arg0 arg1 arg2 arr arg3
-        swap                                # fun this arg0 arg1 arg2 arg3 arr
-        dup                                 # fun this arg0 arg1 arg2 arg3 arr arr
-        int8 4                              # fun this arg0 arg1 arg2 arg3 arr arr 4
-        getelem                             # fun this arg0 arg1 arg2 arg3 arr arg4
-        swap                                # fun this arg0 arg1 arg2 arg3 arg4 arr
-        dup                                 # fun this arg0 arg1 arg2 arg3 arg4 arr arr
-        int8 5                              # fun this arg0 arg1 arg2 arg3 arg4 arr arr 5
-        getelem                             # fun this arg0 arg1 arg2 arg3 arg4 arr arg5
-        swap                                # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr
-        pop                                 # fun this arg0 arg1 arg2 arg3 arg4 arg5
-        call 6                              #
-        stop                                #
-    .end                                    #
-
-    .imacro apply7                          # apply fun this arr
-        pick 3                              # fun this arr apply
-        pop                                 # fun this arr
-        dup                                 # fun this arr arr
-        zero                                # fun this arr arr 0
-        getelem                             # fun this arr arg0
-        swap                                # fun this arg0 arr
-        dup                                 # fun this arg0 arr arr
-        one                                 # fun this arg0 arr arr 1
-        getelem                             # fun this arg0 arr arg1
-        swap                                # fun this arg0 arg1 arr
-        dup                                 # fun this arg0 arg1 arr arr
-        int8 2                              # fun this arg0 arg1 arr arr 2
-        getelem                             # fun this arg0 arg1 arr arg2
-        swap                                # fun this arg0 arg1 arg2 arr
-        dup                                 # fun this arg0 arg1 arg2 arr arr
-        int8 3                              # fun this arg0 arg1 arg2 arr arr 3
-        getelem                             # fun this arg0 arg1 arg2 arr arg3
-        swap                                # fun this arg0 arg1 arg2 arg3 arr
-        dup                                 # fun this arg0 arg1 arg2 arg3 arr arr
-        int8 4                              # fun this arg0 arg1 arg2 arg3 arr arr 4
-        getelem                             # fun this arg0 arg1 arg2 arg3 arr arg4
-        swap                                # fun this arg0 arg1 arg2 arg3 arg4 arr
-        dup                                 # fun this arg0 arg1 arg2 arg3 arg4 arr arr
-        int8 5                              # fun this arg0 arg1 arg2 arg3 arg4 arr arr 5
-        getelem                             # fun this arg0 arg1 arg2 arg3 arg4 arr arg5
-        swap                                # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr
-        dup                                 # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr arr
-        int8 6                              # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr arr 6
-        getelem                             # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr arg6
-        swap                                # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6 arr
-        pop                                 # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6
-        call 7                              #
-        stop                                #
-    .end                                    #
-
-    .imacro apply8                          # apply fun this arr
-        pick 3                              # fun this arr apply
-        pop                                 # fun this arr
-        dup                                 # fun this arr arr
-        zero                                # fun this arr arr 0
-        getelem                             # fun this arr arg0
-        swap                                # fun this arg0 arr
-        dup                                 # fun this arg0 arr arr
-        one                                 # fun this arg0 arr arr 1
-        getelem                             # fun this arg0 arr arg1
-        swap                                # fun this arg0 arg1 arr
-        dup                                 # fun this arg0 arg1 arr arr
-        int8 2                              # fun this arg0 arg1 arr arr 2
-        getelem                             # fun this arg0 arg1 arr arg2
-        swap                                # fun this arg0 arg1 arg2 arr
-        dup                                 # fun this arg0 arg1 arg2 arr arr
-        int8 3                              # fun this arg0 arg1 arg2 arr arr 3
-        getelem                             # fun this arg0 arg1 arg2 arr arg3
-        swap                                # fun this arg0 arg1 arg2 arg3 arr
-        dup                                 # fun this arg0 arg1 arg2 arg3 arr arr
-        int8 4                              # fun this arg0 arg1 arg2 arg3 arr arr 4
-        getelem                             # fun this arg0 arg1 arg2 arg3 arr arg4
-        swap                                # fun this arg0 arg1 arg2 arg3 arg4 arr
-        dup                                 # fun this arg0 arg1 arg2 arg3 arg4 arr arr
-        int8 5                              # fun this arg0 arg1 arg2 arg3 arg4 arr arr 5
-        getelem                             # fun this arg0 arg1 arg2 arg3 arg4 arr arg5
-        swap                                # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr
-        dup                                 # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr arr
-        int8 6                              # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr arr 6
-        getelem                             # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr arg6
-        swap                                # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6 arr
-        dup                                 # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6 arr arr
-        int8 7                              # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6 arr arr 7
-        getelem                             # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6 arr arg7
-        swap                                # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6 arg7 arr
-        pop                                 # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6 arg7
-        call 8                              #
-        stop                                #
-    .end                                    #
-
-    .imacro call0                           # call fun
-        swap                                # fun call
-        pop                                 # fun
-        nullthis                            # fun this
-        call 0                              #
-        stop                                #
-    .end                                    #
-
-    .imacro call1                           # call fun this
-        pick 2                              # fun this call
-        pop                                 # fun this
-        call 0                              #
-        stop                                #
-    .end                                    #
-
-    .imacro call2                           # call fun this arg0
-        pick 3                              # fun this arg0 call
-        pop                                 # fun this arg0
-        call 1                              #
-        stop                                #
-    .end                                    #
-
-    .imacro call3                           # call fun this arg0 arg1
-        pick 4                              # fun this arg0 arg1 call
-        pop                                 # fun this arg0 arg1
-        call 2                              #
-        stop                                #
-    .end                                    #
-
-    .imacro call4                           # call fun this arg0 arg1 arg2
-        pick 5                              # fun this arg0 arg1 arg2 call
-        pop                                 # fun this arg0 arg1 arg2
-        call 3                              #
-        stop                                #
-    .end                                    #
-
-    .imacro call5                           # call fun this arg0 arg1 arg2 arg3
-        pick 6                              # fun this arg0 arg1 arg2 arg3 call
-        pop                                 # fun this arg0 arg1 arg2 arg3
-        call 4                              #
-        stop                                #
-    .end                                    #
-
-    .imacro call6                           # call fun this arg0 arg1 arg2 arg3 arg4
-        pick 7                              # fun this arg0 arg1 arg2 arg3 arg4 call
-        pop                                 # fun this arg0 arg1 arg2 arg3 arg4
-        call 5                              #
-        stop                                #
-    .end                                    #
-
-    .imacro call7                           # call fun this arg0 arg1 arg2 arg3 arg4 arg5
-        pick 8                              # fun this arg0 arg1 arg2 arg3 arg4 arg5 call
-        pop                                 # fun this arg0 arg1 arg2 arg3 arg4 arg5
-        call 6                              #
-        stop                                #
-    .end                                    #
-
-    .imacro call8                           # call fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6
-        pick 9                              # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6 call
-        pop                                 # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6
-        call 7                              #
-        stop                                #
-    .end                                    #
-
-.end
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -3333,24 +3333,16 @@ js_Interpret(JSContext *cx)
 
           BEGIN_CASE(JSOP_SWAP)
             JS_ASSERT(regs.sp - 2 >= StackBase(fp));
             lval = FETCH_OPND(-2);
             rval = FETCH_OPND(-1);
             STORE_OPND(-1, lval);
             STORE_OPND(-2, rval);
           END_CASE(JSOP_SWAP)
-          
-          BEGIN_CASE(JSOP_PICK)
-            i = regs.pc[1];
-            JS_ASSERT(regs.sp - (i+1) >= StackBase(fp));
-            lval = regs.sp[-(i+1)];
-            memmove(regs.sp - (i+1), regs.sp - i, sizeof(jsval)*i);
-            regs.sp[-1] = lval;
-          END_CASE(JSOP_PICK)
 
 #define PROPERTY_OP(n, call)                                                  \
     JS_BEGIN_MACRO                                                            \
         /* Fetch the left part and resolve it to a non-null object. */        \
         FETCH_OBJECT(cx, n, lval, obj);                                       \
                                                                               \
         /* Get or set the property. */                                        \
         if (!call)                                                            \
@@ -4803,24 +4795,138 @@ js_Interpret(JSContext *cx)
                 }
             }
 
             if (!js_InvokeConstructor(cx, argc, JS_FALSE, vp))
                 goto error;
             regs.sp = vp + 1;
             LOAD_INTERRUPT_HANDLER(cx);
           END_CASE(JSOP_NEW)
+
+          BEGIN_CASE(JSOP_APPLY)
+          {
+            argc = GET_ARGC(regs.pc);
+            vp = regs.sp - (argc + 2);
+            lval = *vp;
+            if (!VALUE_IS_FUNCTION(cx, lval))
+                goto do_call;
+            obj = JSVAL_TO_OBJECT(lval);
+            fun = GET_FUNCTION_PRIVATE(cx, obj);
+            if (FUN_INTERPRETED(fun))
+                goto do_call;
+
+            bool apply = (JSFastNative)fun->u.n.native == js_fun_apply;
+            if (!apply && (JSFastNative)fun->u.n.native != js_fun_call)
+                goto do_call;
+
+            /* 
+             * If the second arg to apply is null or void, treat it as an empty
+             * array.
+             */
+            jsuint applylen = 0;
+            if (apply && argc >= 2 &&
+                !JSVAL_IS_VOID(vp[3]) && !JSVAL_IS_NULL(vp[3])) {
+                /* 
+                 * Fall back on js_Invoke when the array argument has a wrong
+                 * type or when it has too many elements to fit into the
+                 * current stack chunk.
+                 */
+                if (!JSVAL_IS_OBJECT(vp[3]))
+                    goto do_call;
+
+                JSBool arraylike;
+                JSObject* aobj = JSVAL_TO_OBJECT(vp[3]);
+                if (!js_IsArrayLike(cx, aobj, &arraylike, &applylen))
+                    goto error;
+                if (!arraylike || applylen > ARGC_LIMIT)
+                    goto do_call;
+
+                JSArena *a = cx->stackPool.current;
+                JS_ASSERT(jsuword(vp + 2) <= a->limit);
+
+                /*
+                 * We need space for applylen elements plus an extra slot to
+                 * temporary root the array object when we unpack its elements
+                 * using OBJ_GET_PROPERTY below.
+                 */
+                if (a->limit - jsuword(vp + 2) < (applylen + 1) * sizeof(jsval))
+                    goto do_call;
+            }
+
+            if (!VALUE_IS_FUNCTION(cx, vp[1]))
+                goto do_call;
+            vp[0] = vp[1];
+
+            if (argc == 0) {
+                /* 
+                 * Call fun with its global object as the 'this' param if 
+                 * no args. 
+                 */
+                obj = NULL;
+            } else {
+                /* Convert the first arg to 'this'. */
+                if (!JSVAL_IS_PRIMITIVE(vp[2]))
+                    obj = JSVAL_TO_OBJECT(vp[2]);
+                else if (!js_ValueToObject(cx, vp[2], &obj))
+                    goto error;
+            }
+            vp[1] = OBJECT_TO_JSVAL(obj);
+
+            if (!apply) {
+                if (argc != 0) {
+                    --argc;
+                    memmove(vp + 2, vp + 3, argc * sizeof *vp);
+                }
+            } else if (applylen == 0) {
+                argc = 0;
+            } else {
+                /* 
+                 * Make room for missing arguments to the right including the
+                 * temporary root nulling any extra stack slots for GC safety.
+                 */
+                jsval* newsp = vp + 2 + applylen + 1;
+                if (newsp > regs.sp) {
+                    JSArena *a = cx->stackPool.current;
+                    JS_ASSERT(jsuword(newsp) <= a->limit); /* see above */
+                    if ((jsuword) newsp > a->avail)
+                        a->avail = (jsuword) newsp;
+                    memset(vp + 2 + argc, 0, (applylen - argc) * sizeof(jsval));
+                }
+
+                JSObject *aobj = JSVAL_TO_OBJECT(vp[3]);
+                newsp[-1] = vp[3];
+                regs.sp = newsp;
+
+                /* Expand array content onto the stack. */
+                for (i = 0; i < jsint(applylen); i++) {
+                    id = INT_TO_JSID(i);
+                    if (!OBJ_GET_PROPERTY(cx, aobj, id, &vp[2 + i])) {
+                        /* 
+                         * There is no good way to restore the original stack
+                         * state here, but it is in a reasonable  state with
+                         * either original elements or nulls for all arguments
+                         * we didn't unpack yet, so we leave it at that.
+                         */
+                        goto error;
+                    }
+                }
+                argc = applylen;
+            }
+            regs.sp = vp + 2 + argc;
+            TRACE_1(ApplyComplete, argc);
+            goto do_call_with_specified_vp_and_argc;
+          }
           
           BEGIN_CASE(JSOP_CALL)
           BEGIN_CASE(JSOP_EVAL)
-          BEGIN_CASE(JSOP_APPLY)
           do_call:
             argc = GET_ARGC(regs.pc);
             vp = regs.sp - (argc + 2);
             
+          do_call_with_specified_vp_and_argc:
             lval = *vp;
             if (VALUE_IS_FUNCTION(cx, lval)) {
                 obj = JSVAL_TO_OBJECT(lval);
                 fun = GET_FUNCTION_PRIVATE(cx, obj);
 
                 /* Clear frame flags since this is not a constructor call. */
                 flags = 0;
                 if (FUN_INTERPRETED(fun))
@@ -6842,16 +6948,17 @@ js_Interpret(JSContext *cx)
           L_JSOP_TOATTRNAME:
           L_JSOP_QNAME:
           L_JSOP_QNAMECONST:
           L_JSOP_QNAMEPART:
           L_JSOP_ANYNAME:
           L_JSOP_DEFXMLNS:
 # endif
 
+          L_JSOP_UNUSED201:
           L_JSOP_UNUSED202:
           L_JSOP_UNUSED203:
           L_JSOP_UNUSED204:
           L_JSOP_UNUSED205:
           L_JSOP_UNUSED206:
           L_JSOP_UNUSED207:
           L_JSOP_UNUSED208:
           L_JSOP_UNUSED209:
--- a/js/src/jsopcode.tbl
+++ b/js/src/jsopcode.tbl
@@ -189,17 +189,17 @@ OPDEF(JSOP_AND,       69, "and",        
 OPDEF(JSOP_TABLESWITCH,  70, "tableswitch",  NULL,   -1,  1,  0,  0,  JOF_TABLESWITCH|JOF_DETECTING|JOF_PARENHEAD)
 OPDEF(JSOP_LOOKUPSWITCH, 71, "lookupswitch", NULL,   -1,  1,  0,  0,  JOF_LOOKUPSWITCH|JOF_DETECTING|JOF_PARENHEAD)
 
 /* New, infallible/transitive identity ops. */
 OPDEF(JSOP_STRICTEQ,  72, "stricteq",   "===",        1,  2,  1, 10,  JOF_BYTE|JOF_DETECTING|JOF_LEFTASSOC)
 OPDEF(JSOP_STRICTNE,  73, "strictne",   "!==",        1,  2,  1, 10,  JOF_BYTE|JOF_DETECTING|JOF_LEFTASSOC)
 
 /* Variant of JSOP_NULL for default (global) |this| parameter pushing. */
-OPDEF(JSOP_NULLTHIS,  74, "nullthis",   "nullthis",   1,  0,  1, 19,  JOF_BYTE)
+OPDEF(JSOP_NULLTHIS,  74, js_null_str,  js_null_str,  1,  0,  1, 19,  JOF_BYTE)
 
 /*
  * JSOP_ITER sets up a for-in or for-each-in loop using the JSITER_* flag bits
  * in this op's uint8 immediate operand. It replaces the top of stack object
  * with an iterator for that object, and pushes a slot used by JSOP_NEXTITER.
  *
  * JSOP_NEXTITER stores the next iterated value in the top of stack slot which
  * was allocated by JSOP_ITER and pushes true, or stores JSVAL_HOLE and pushes
@@ -479,22 +479,17 @@ OPDEF(JSOP_CALLXMLNAME,   197, "callxmln
  */
 OPDEF(JSOP_TYPEOFEXPR,    198,"typeofexpr",  NULL,    1,  1,  1, 15,  JOF_BYTE|JOF_DETECTING)
 
 /*
  * Block-local scope support.
  */
 OPDEF(JSOP_ENTERBLOCK,    199,"enterblock",  NULL,    3,  0, -1,  0,  JOF_OBJECT)
 OPDEF(JSOP_LEAVEBLOCK,    200,"leaveblock",  NULL,    3, -1,  0,  0,  JOF_UINT16)
-
-/*
- * Pick an element from the stack.
- */
-OPDEF(JSOP_PICK,          201,"pick",        NULL,    2,  1,  0,  0,  JOF_UINT8)
-
+OPDEF(JSOP_UNUSED201,     201,"unused201",   NULL,    1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED202,     202,"unused202",   NULL,    1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED203,     203,"unused203",   NULL,    1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED204,     204,"unused204",   NULL,    1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED205,     205,"unused205",   NULL,    1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED206,     206,"unused206",   NULL,    1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED207,     207,"unused207",   NULL,    1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED208,     208,"unused208",   NULL,    1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED209,     209,"unused209",   NULL,    1,  0,  0,  0,  JOF_BYTE)
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -1830,19 +1830,19 @@ TraceRecorder::determineSlotType(jsval* 
         : JSVAL_TAG(*vp);
     JS_ASSERT((m != JSVAL_INT) || isInt32(*vp));
     return m;
 }
 
 /*
  * Combine fp->imacpc and fp->regs->pc into one word, with 8 bits for the pc
  * adjustment from one byte before the imacro's start (so a 0 high byte means
- * we're not in an imacro), and 22 for the pc adjustment from script->code.
+ * we're not in an imacro), and 24 for the pc adjustment from script->code.
  */
-#define IMACRO_PC_ADJ_BITS   10
+#define IMACRO_PC_ADJ_BITS   8
 #define SCRIPT_PC_ADJ_BITS   (32 - IMACRO_PC_ADJ_BITS)
 
 // The stored imacro_pc_adj byte offset is biased by 1.
 #define IMACRO_PC_ADJ_LIMIT  (JS_BIT(IMACRO_PC_ADJ_BITS) - 1)
 #define SCRIPT_PC_ADJ_LIMIT  JS_BIT(SCRIPT_PC_ADJ_BITS)
 
 #define IMACRO_PC_ADJ(ip)    ((uintptr_t)(ip) >> SCRIPT_PC_ADJ_BITS)
 #define SCRIPT_PC_ADJ(ip)    ((ip) & JS_BITMASK(SCRIPT_PC_ADJ_BITS))
@@ -1869,17 +1869,16 @@ TraceRecorder::determineSlotType(jsval* 
                                 (fp)->regs->pc = imacro_code[*(fp)->imacpc] + \
                                                  IMACRO_PC_ADJ(ip)            \
                               : (fp)->regs->pc = (fp)->script->code + (ip))
 
 static jsbytecode* imacro_code[JSOP_LIMIT];
 
 JS_STATIC_ASSERT(sizeof(binary_imacros) < IMACRO_PC_ADJ_LIMIT);
 JS_STATIC_ASSERT(sizeof(add_imacros) < IMACRO_PC_ADJ_LIMIT);
-JS_STATIC_ASSERT(sizeof(apply_imacros) < IMACRO_PC_ADJ_LIMIT);
 
 JS_REQUIRES_STACK LIns*
 TraceRecorder::snapshot(ExitType exitType)
 {
     JSStackFrame* fp = cx->fp;
     JSFrameRegs* regs = fp->regs;
     jsbytecode* pc = regs->pc;
     if (exitType == BRANCH_EXIT && js_IsLoopExit(pc, (jsbytecode*)fragment->root->ip))
@@ -5578,29 +5577,16 @@ TraceRecorder::record_JSOP_SWAP()
     LIns* l_ins = get(&l);
     LIns* r_ins = get(&r);
     set(&r, l_ins);
     set(&l, r_ins);
     return true;
 }
 
 JS_REQUIRES_STACK bool
-TraceRecorder::record_JSOP_PICK()
-{
-    jsval* sp = cx->fp->regs->sp;
-    jsuint n = cx->fp->regs->pc[1];
-    JS_ASSERT(sp - (n+1) >= StackBase(cx->fp));
-    LIns* top = tracker.get(sp - (n+1));
-    for (jsint i = 0; i < n; ++i)
-        tracker.set(sp - (n+1) + i, tracker.get(sp - n + i));
-    tracker.set(&sp[-1], top);
-    return true;
-}
-
-JS_REQUIRES_STACK bool
 TraceRecorder::record_JSOP_SETCONST()
 {
     return false;
 }
 
 JS_REQUIRES_STACK bool
 TraceRecorder::record_JSOP_BITOR()
 {
@@ -6588,118 +6574,173 @@ TraceRecorder::interpretedFunctionCall(j
 }
 
 JS_REQUIRES_STACK bool
 TraceRecorder::record_JSOP_CALL()
 {
     return functionCall(false, GET_ARGC(cx->fp->regs->pc));
 }
 
-static jsbytecode* apply_imacro_table[] = {
-    apply_imacros.apply0,
-    apply_imacros.apply1,
-    apply_imacros.apply2,
-    apply_imacros.apply3,
-    apply_imacros.apply4,
-    apply_imacros.apply5,
-    apply_imacros.apply6,
-    apply_imacros.apply7,
-    apply_imacros.apply8
-};
-
-static jsbytecode* call_imacro_table[] = {
-    apply_imacros.call0,
-    apply_imacros.call1,
-    apply_imacros.call2,
-    apply_imacros.call3,
-    apply_imacros.call4,
-    apply_imacros.call5,
-    apply_imacros.call6,
-    apply_imacros.call7,
-    apply_imacros.call8
-};
-
 JS_REQUIRES_STACK bool
 TraceRecorder::record_JSOP_APPLY()
 {
     JSStackFrame* fp = cx->fp;
     jsbytecode *pc = fp->regs->pc;
     uintN argc = GET_ARGC(pc);
     jsval* vp = fp->regs->sp - (argc + 2);
     JS_ASSERT(vp >= StackBase(fp));
     jsuint length = 0;
     JSObject* aobj = NULL;
     LIns* aobj_ins = NULL;
-    
-    JS_ASSERT(!fp->imacpc);
+    LIns* dslots_ins = NULL;
     
     if (!VALUE_IS_FUNCTION(cx, vp[0]))
         return record_JSOP_CALL();
 
     JSObject* obj = JSVAL_TO_OBJECT(vp[0]);
     JSFunction* fun = GET_FUNCTION_PRIVATE(cx, obj);
     if (FUN_INTERPRETED(fun))
         return record_JSOP_CALL();
 
     bool apply = (JSFastNative)fun->u.n.native == js_fun_apply;
     if (!apply && (JSFastNative)fun->u.n.native != js_fun_call)
         return record_JSOP_CALL();
 
-    /*
-     * We don't trace apply and call with a primitive 'this', which is the
-     * first positional parameter.
+    /* 
+     * If this is apply, and the argument is too long and would need
+     * a separate stack chunk, do a heavy-weight apply. 
      */
-    if (argc > 0 && JSVAL_IS_PRIMITIVE(vp[2]))
-        return record_JSOP_CALL();
-    
-    /*
-     * Guard on the identity of this, which is the function we are applying.
-     */
-    if (!guardCallee(vp[1]))
-        return false;
-
     if (apply && argc >= 2) {
-        if (argc != 2)
-            ABORT_TRACE("apply with excess arguments");
         if (JSVAL_IS_PRIMITIVE(vp[3]))
             ABORT_TRACE("arguments parameter of apply is primitive");
         aobj = JSVAL_TO_OBJECT(vp[3]);
         aobj_ins = get(&vp[3]);
-
+        
         /* 
          * We expect a dense array for the arguments (the other
          * frequent case is the arguments object, but that we
          * don't trace at the moment). 
          */
+        guard(false, lir->ins_eq0(aobj_ins), MISMATCH_EXIT);
         if (!guardDenseArray(aobj, aobj_ins))
             ABORT_TRACE("arguments parameter of apply is not a dense array");
         
         /*
-         * We trace only apply calls with a certain number of arguments.
-         */
-        length = jsuint(aobj->fslots[JSSLOT_ARRAY_LENGTH]);
-        if (length >= JS_ARRAY_LENGTH(apply_imacro_table))
-            ABORT_TRACE("too many arguments to apply");
-        
-        /*
          * Make sure the array has the same length at runtime.
          */
-        guard(true, 
-              lir->ins2i(LIR_eq,
-                         stobj_get_fslot(aobj_ins, JSSLOT_ARRAY_LENGTH),
-                         length), 
-              BRANCH_EXIT);
+        length = jsuint(aobj->fslots[JSSLOT_ARRAY_LENGTH]);
+        guard(true, lir->ins2i(LIR_eq,
+                               stobj_get_fslot(aobj_ins, JSSLOT_ARRAY_LENGTH),
+                               length), 
+                               BRANCH_EXIT);
+ 
+        /* 
+         * Make sure dslots is not NULL and guard the array's capacity.
+         */
+        dslots_ins = lir->insLoad(LIR_ldp, aobj_ins, offsetof(JSObject, dslots));
+        guard(false,
+              lir->ins_eq0(dslots_ins),
+              MISMATCH_EXIT);
+        guard(true,
+              lir->ins2(LIR_ult,
+                        lir->insImm(length),
+                        lir->insLoad(LIR_ldp, dslots_ins, 0 - (int)sizeof(jsval))),
+              MISMATCH_EXIT);
         
-        return call_imacro(apply_imacro_table[length]);
+        /*
+         * The interpreter deoptimizes if we are about to cross a stack chunk by
+         * re-entering itself indirectly from js_Invoke, and we can't trace that 
+         * case.
+         */
+        length = (uintN)JS_MIN(length, ARRAY_INIT_LIMIT - 1);
+        jsval* newsp = vp + 2 + length;
+        JS_ASSERT(newsp >= vp + 2);
+        JSArena *a = cx->stackPool.current;
+        if (jsuword(newsp) > a->limit)
+            ABORT_TRACE("apply or call across stack-chunks");
+    }
+
+    /* Protect against a non-function callee. */
+    if (!VALUE_IS_FUNCTION(cx, vp[1]))
+        ABORT_TRACE("apply on a non-function");
+
+    /*
+     * Guard on the identity of this, which is the function we
+     * are applying.
+     */
+    if (!guardCallee(vp[1]))
+        return false;
+
+    LIns* callee_ins = get(&vp[1]);
+    LIns* this_ins = NULL;
+    if (argc > 0) {
+        this_ins = get(&vp[2]);
+        if (JSVAL_IS_PRIMITIVE(vp[2]))
+            ABORT_TRACE("apply with primitive this");
+    } else {
+        this_ins = lir->insImm(0);
     }
     
-    if (argc >= JS_ARRAY_LENGTH(call_imacro_table))
-        ABORT_TRACE("too many arguments to call");
-    
-    return call_imacro(call_imacro_table[argc]);
+    LIns** argv;
+    if (argc >= 2) {
+        if (!apply) {
+            --argc;
+            JS_ASSERT(argc >= 0);
+            argv = (LIns**) alloca(sizeof(LIns*) * argc);
+            for (jsuint n = 0; n < argc; ++n)
+                argv[n] = get(&vp[3 + n]); /* skip over the this parameter */
+        } else {
+            /*
+             * We already established that argments is a dense array
+             * and we know its length and we know dslots is not NULL
+             * and the length is not beyond the dense array's capacity. 
+             */
+            argc = length;
+            JS_ASSERT(argc >= 0);
+            argv = (LIns**) alloca(sizeof(LIns*) * argc);
+            for (unsigned n = 0; n < argc; ++n) {
+                /* Load the value and guard on its type to unbox it. */
+                LIns* v_ins = lir->insLoadi(dslots_ins, n * sizeof(jsval));
+                /* 
+                 * We can't "see through" a hole to a possible Array.prototype property, so
+                 * we abort here and guard below (after unboxing).
+                 */
+                jsval* dp = &aobj->dslots[n];
+                if (*dp == JSVAL_HOLE)
+                    ABORT_TRACE("can't see through hole in dense array");
+                if (!unbox_jsval(*dp, v_ins))
+                    return false;
+                if (JSVAL_TAG(*dp) == JSVAL_BOOLEAN) {
+                    // Optimize to guard for a hole only after untagging, so we know that
+                    // we have a boolean, to avoid an extra guard for non-boolean values.
+                    guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_HOLE))),
+                          MISMATCH_EXIT);
+                }
+                argv[n] = v_ins;
+            }
+        }
+    } else {
+        argc = 0;
+    }
+    /*
+     * We have all arguments unpacked and we are now ready to modify the
+     * tracker.
+     */
+    tracker.set(&vp[0], callee_ins);
+    tracker.set(&vp[1], this_ins);
+    for (unsigned n = 0; n < argc; ++n)
+        tracker.set(&vp[2 + n], argv[n]);
+
+    return true;
+}
+
+JS_REQUIRES_STACK bool
+TraceRecorder::record_ApplyComplete(uintN argc)
+{
+    return functionCall(false, argc);
 }
 
 JS_REQUIRES_STACK bool
 TraceRecorder::record_FastNativeCallComplete()
 {
     JS_ASSERT(pendingTraceableNative);
     
     /* At this point the generated code has already called the native function
@@ -8512,21 +8553,21 @@ InitIMacroCode()
     for (uintN op = JSOP_BITOR; op <= JSOP_MOD; op++)
         imacro_code[op] = (jsbytecode*)&binary_imacros - 1;
 
     // NB: above loop mis-set JSOP_ADD's entry, so order here is crucial.
     imacro_code[JSOP_ADD] = (jsbytecode*)&add_imacros - 1;
 
     imacro_code[JSOP_ITER] = (jsbytecode*)&iter_imacros - 1;
     imacro_code[JSOP_NEXTITER] = nextiter_imacro - 1;
-    imacro_code[JSOP_APPLY] = (jsbytecode*)&apply_imacros - 1;
 }
 
 #define UNUSED(n) JS_REQUIRES_STACK bool TraceRecorder::record_JSOP_UNUSED##n() { return false; }
 
+UNUSED(201)
 UNUSED(202)
 UNUSED(203)
 UNUSED(204)
 UNUSED(205)
 UNUSED(206)
 UNUSED(207)
 UNUSED(208)
 UNUSED(209)
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -455,16 +455,17 @@ public:
 
     JS_REQUIRES_STACK bool record_EnterFrame();
     JS_REQUIRES_STACK bool record_LeaveFrame();
     JS_REQUIRES_STACK bool record_SetPropHit(JSPropCacheEntry* entry, JSScopeProperty* sprop);
     JS_REQUIRES_STACK bool record_SetPropMiss(JSPropCacheEntry* entry);
     JS_REQUIRES_STACK bool record_DefLocalFunSetSlot(uint32 slot, JSObject* obj);
     JS_REQUIRES_STACK bool record_FastNativeCallComplete();
     JS_REQUIRES_STACK bool record_IteratorNextComplete();
+    JS_REQUIRES_STACK bool record_ApplyComplete(uintN argc);
 
     nanojit::Fragment* getOuterToBlacklist() { return outerToBlacklist; }
     void deepAbort() { deepAborted = true; }
     bool wasDeepAborted() { return deepAborted; }
     bool walkedOutOfLoop() { return terminate; }
     void setPromotedPeer(nanojit::Fragment* peer) { promotedPeer = peer; }
     TreeInfo* getTreeInfo() { return treeInfo; }
 
@@ -493,17 +494,17 @@ public:
 #define RECORD_ARGS(x,args)                                                   \
     JS_BEGIN_MACRO                                                            \
         if (!js_MonitorRecording(TRACE_RECORDER(cx))) {                       \
             ENABLE_TRACER(0);                                                 \
         } else {                                                              \
             TRACE_ARGS_(x, args,                                              \
                 if ((fp->flags & JSFRAME_IMACRO_START) &&                     \
                     (x == JSOP_ITER || x == JSOP_NEXTITER ||                  \
-                     x == JSOP_APPLY || JSOP_IS_BINARY(x))) {                 \
+                    JSOP_IS_BINARY(x))) {                                     \
                     fp->flags &= ~JSFRAME_IMACRO_START;                       \
                     atoms = COMMON_ATOMS_START(&rt->atomState);               \
                     op = JSOp(*regs.pc);                                      \
                     DO_OP();                                                  \
                 }                                                             \
             );                                                                \
          }                                                                    \
     JS_END_MACRO
--- a/js/src/trace-test.js
+++ b/js/src/trace-test.js
@@ -3723,73 +3723,16 @@ load("mandelbrot-results.js");
 
   escape = escapeNorm2;
   doImageData = false;  // avoidSparseArray doesn't matter here
   test(createMandelSet);
 //}
 //testMandelbrotAll();
 // END MANDELBROT STUFF
 
-function testApplyCallHelper(f) {
-    var r = [];
-    for (var i = 0; i < 10; ++i) f.call(); 
-    r.push(x);
-    for (var i = 0; i < 10; ++i) f.call(this);
-    r.push(x);
-    for (var i = 0; i < 10; ++i) f.apply(this);
-    r.push(x);
-    for (var i = 0; i < 10; ++i) f.call(this,0);
-    r.push(x);
-    for (var i = 0; i < 10; ++i) f.apply(this,[0]);
-    r.push(x);
-    for (var i = 0; i < 10; ++i) f.call(this,0,1);
-    r.push(x);
-    for (var i = 0; i < 10; ++i) f.apply(this,[0,1]);
-    r.push(x);
-    for (var i = 0; i < 10; ++i) f.call(this,0,1,2);
-    r.push(x);
-    for (var i = 0; i < 10; ++i) f.apply(this,[0,1,2]);
-    r.push(x);
-    for (var i = 0; i < 10; ++i) f.call(this,0,1,2,3);
-    r.push(x);
-    for (var i = 0; i < 10; ++i) f.apply(this,[0,1,2,3]);
-    r.push(x);
-    for (var i = 0; i < 10; ++i) f.call(this,0,1,2,3,4);
-    r.push(x);
-    for (var i = 0; i < 10; ++i) f.apply(this,[0,1,2,3,4]);
-    r.push(x);
-    for (var i = 0; i < 10; ++i) f.call(this,0,1,2,3,4,5);
-    r.push(x);
-    for (var i = 0; i < 10; ++i) f.apply(this,[0,1,2,3,4,5])
-    r.push(x);
-    return(r.join(","));
-}
-function testApplyCall() {
-    var r = testApplyCallHelper(function (a0,a1,a2,a3,a4,a5,a6,a7) { x = [a0,a1,a2,a3,a4,a5,a6,a7]; });
-    r += testApplyCallHelper(function (a0,a1,a2,a3,a4,a5,a6,a7) { x = [a0,a1,a2,a3,a4,a5,a6,a7]; });
-    return r;
-}
-testApplyCall.expected = 
-",,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,,0,,,,,,,,0,1,,,,,,,0,1,,,,,,,0,1,2,,,,,,0,1,2,,,,,,0,1,2,3,,,,,0,1,2,3,,,,,0,1,2,3,4,,,,0,1,2,3,4,,,,0,1,2,3,4,5,,,0,1,2,3,4,5,," +
-",,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,,0,,,,,,,,0,1,,,,,,,0,1,,,,,,,0,1,2,,,,,,0,1,2,,,,,,0,1,2,3,,,,,0,1,2,3,,,,,0,1,2,3,4,,,,0,1,2,3,4,,,,0,1,2,3,4,5,,,0,1,2,3,4,5,,";
-test(testApplyCall);
-
-function testApplyUnboxHelper(f,a) {
-    var q;
-    for (var i = 0; i < 10; ++i)
-        q = f.apply(f,a);
-    return q;
-}
-function testApplyUnbox() {
-    var f = function(x) { return x; }
-    return [testApplyUnboxHelper(f,[1]), testApplyUnboxHelper(f,[true])].join(",");
-}
-testApplyUnbox.expected = "1,true";
-test(testApplyUnbox);
-
 /* NOTE: Keep this test last, since it screws up all for...in loops after it. */
 function testGlobalProtoAccess() {
     return "ok";
 }
 this.__proto__.a = 3; for (var j = 0; j < 4; ++j) { [a]; }
 testGlobalProtoAccess.expected = "ok";
 test(testGlobalProtoAccess);