[JAEGER] Add NAMEINC; make NAMEINC ops fast (bug 578740).
authorDavid Anderson <danderson@mozilla.com>
Wed, 14 Jul 2010 21:38:14 -0700
changeset 53118 eff02554170ae71c7a9144e557f678b330c4cc83
parent 53117 6b16e94e8d2f06db79c4a5a9295f85a5c78f484e
child 53119 d83e40b415682d6d233a02be09751b54ef01f6e4
push id15660
push userrsayre@mozilla.com
push dateSat, 11 Sep 2010 19:16:24 +0000
treeherdermozilla-central@f1bd314e64ac [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs578740
milestone2.0b2pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
[JAEGER] Add NAMEINC; make NAMEINC ops fast (bug 578740).
js/src/jsemit.cpp
js/src/jsopcode.tbl
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/PolyIC.cpp
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -186,18 +186,30 @@ UpdateDepth(JSContext *cx, JSCodeGenerat
 #else
     extra = 0;
 #endif
     if ((cs->format & JOF_TMPSLOT_MASK) || extra) {
         depth = (uintN) cg->stackDepth +
                 ((cs->format & JOF_TMPSLOT_MASK) >> JOF_TMPSLOT_SHIFT) +
                 extra;
         /* :TODO: hack - remove later. */
-        if (op == JSOP_PROPINC || op == JSOP_PROPDEC)
-            depth++;
+        switch (op) {
+          case JSOP_PROPINC:
+          case JSOP_PROPDEC:
+            depth += 1;
+            break;
+          case JSOP_NAMEINC:
+          case JSOP_NAMEDEC:
+          case JSOP_INCNAME:
+          case JSOP_DECNAME:
+            depth += 2;
+            break;
+          default:
+            break;
+        }
         if (depth > cg->maxStackDepth)
             cg->maxStackDepth = depth;
     }
 
     nuses = js_GetStackUses(cs, op, pc);
     cg->stackDepth -= nuses;
     JS_ASSERT(cg->stackDepth >= 0);
     if (cg->stackDepth < 0) {
--- a/js/src/jsopcode.tbl
+++ b/js/src/jsopcode.tbl
@@ -153,26 +153,26 @@ OPDEF(JSOP_BITNOT,    33, "bitnot",     
 OPDEF(JSOP_NEG,       34, "neg",        "- ",         1,  1,  1, 15,  JOF_BYTE)
 OPDEF(JSOP_POS,       35, "pos",        "+ ",         1,  1,  1, 15,  JOF_BYTE)
 OPDEF(JSOP_DELNAME,   36, "delname",    NULL,         3,  0,  1, 15,  JOF_ATOM|JOF_NAME|JOF_DEL)
 OPDEF(JSOP_DELPROP,   37, "delprop",    NULL,         3,  1,  1, 15,  JOF_ATOM|JOF_PROP|JOF_DEL)
 OPDEF(JSOP_DELELEM,   38, "delelem",    NULL,         1,  2,  1, 15,  JOF_BYTE |JOF_ELEM|JOF_DEL)
 OPDEF(JSOP_TYPEOF,    39, js_typeof_str,NULL,         1,  1,  1, 15,  JOF_BYTE|JOF_DETECTING)
 OPDEF(JSOP_VOID,      40, js_void_str,  NULL,         1,  1,  1, 15,  JOF_BYTE)
 
-OPDEF(JSOP_INCNAME,   41, "incname",    NULL,         3,  0,  1, 15,  JOF_ATOM|JOF_NAME|JOF_INC|JOF_TMPSLOT2)
+OPDEF(JSOP_INCNAME,   41, "incname",    NULL,         3,  0,  1, 15,  JOF_ATOM|JOF_NAME|JOF_INC|JOF_TMPSLOT3)
 OPDEF(JSOP_INCPROP,   42, "incprop",    NULL,         3,  1,  1, 15,  JOF_ATOM|JOF_PROP|JOF_INC|JOF_TMPSLOT3)
 OPDEF(JSOP_INCELEM,   43, "incelem",    NULL,         1,  2,  1, 15,  JOF_BYTE |JOF_ELEM|JOF_INC|JOF_TMPSLOT2)
-OPDEF(JSOP_DECNAME,   44, "decname",    NULL,         3,  0,  1, 15,  JOF_ATOM|JOF_NAME|JOF_DEC|JOF_TMPSLOT2)
+OPDEF(JSOP_DECNAME,   44, "decname",    NULL,         3,  0,  1, 15,  JOF_ATOM|JOF_NAME|JOF_DEC|JOF_TMPSLOT3)
 OPDEF(JSOP_DECPROP,   45, "decprop",    NULL,         3,  1,  1, 15,  JOF_ATOM|JOF_PROP|JOF_DEC|JOF_TMPSLOT3)
 OPDEF(JSOP_DECELEM,   46, "decelem",    NULL,         1,  2,  1, 15,  JOF_BYTE |JOF_ELEM|JOF_DEC|JOF_TMPSLOT2)
-OPDEF(JSOP_NAMEINC,   47, "nameinc",    NULL,         3,  0,  1, 15,  JOF_ATOM|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT2)
+OPDEF(JSOP_NAMEINC,   47, "nameinc",    NULL,         3,  0,  1, 15,  JOF_ATOM|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT3)
 OPDEF(JSOP_PROPINC,   48, "propinc",    NULL,         3,  1,  1, 15,  JOF_ATOM|JOF_PROP|JOF_INC|JOF_POST|JOF_TMPSLOT3)
 OPDEF(JSOP_ELEMINC,   49, "eleminc",    NULL,         1,  2,  1, 15,  JOF_BYTE |JOF_ELEM|JOF_INC|JOF_POST|JOF_TMPSLOT2)
-OPDEF(JSOP_NAMEDEC,   50, "namedec",    NULL,         3,  0,  1, 15,  JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT2)
+OPDEF(JSOP_NAMEDEC,   50, "namedec",    NULL,         3,  0,  1, 15,  JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT3)
 OPDEF(JSOP_PROPDEC,   51, "propdec",    NULL,         3,  1,  1, 15,  JOF_ATOM|JOF_PROP|JOF_DEC|JOF_POST|JOF_TMPSLOT3)
 OPDEF(JSOP_ELEMDEC,   52, "elemdec",    NULL,         1,  2,  1, 15,  JOF_BYTE |JOF_ELEM|JOF_DEC|JOF_POST|JOF_TMPSLOT2)
 
 OPDEF(JSOP_GETPROP,   53, "getprop",    NULL,         3,  1,  1, 18,  JOF_ATOM|JOF_PROP)
 OPDEF(JSOP_SETPROP,   54, "setprop",    NULL,         3,  2,  1,  3,  JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
 OPDEF(JSOP_GETELEM,   55, "getelem",    NULL,         1,  2,  1, 18,  JOF_BYTE |JOF_ELEM|JOF_LEFTASSOC)
 OPDEF(JSOP_SETELEM,   56, "setelem",    NULL,         1,  3,  1,  3,  JOF_BYTE |JOF_ELEM|JOF_SET|JOF_DETECTING)
 OPDEF(JSOP_CALLNAME,  57, "callname",   NULL,         3,  0,  2, 19,  JOF_ATOM|JOF_NAME|JOF_CALLOP)
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -635,67 +635,75 @@ mjit::Compiler::generateMethod()
 
           BEGIN_CASE(JSOP_VOID)
             frame.pop();
             frame.push(UndefinedValue());
           END_CASE(JSOP_VOID)
 
           BEGIN_CASE(JSOP_INCNAME)
             jsop_nameinc(op, stubs::IncName, fullAtomIndex(PC));
+            break;
           END_CASE(JSOP_INCNAME)
 
           BEGIN_CASE(JSOP_INCGNAME)
-            jsop_nameinc(op, stubs::IncGlobalName, fullAtomIndex(PC));
+            jsop_gnameinc(op, stubs::IncGlobalName, fullAtomIndex(PC));
           END_CASE(JSOP_INCGNAME)
 
           BEGIN_CASE(JSOP_INCPROP)
             jsop_propinc(op, stubs::IncProp, fullAtomIndex(PC));
             break;
           END_CASE(JSOP_INCPROP)
 
           BEGIN_CASE(JSOP_INCELEM)
             jsop_eleminc(op, stubs::IncElem);
           END_CASE(JSOP_INCELEM)
 
           BEGIN_CASE(JSOP_DECNAME)
             jsop_nameinc(op, stubs::DecName, fullAtomIndex(PC));
+            break;
           END_CASE(JSOP_DECNAME)
 
           BEGIN_CASE(JSOP_DECGNAME)
-            jsop_nameinc(op, stubs::DecGlobalName, fullAtomIndex(PC));
+            jsop_gnameinc(op, stubs::DecGlobalName, fullAtomIndex(PC));
           END_CASE(JSOP_DECGNAME)
 
           BEGIN_CASE(JSOP_DECPROP)
             jsop_propinc(op, stubs::DecProp, fullAtomIndex(PC));
             break;
           END_CASE(JSOP_DECPROP)
 
           BEGIN_CASE(JSOP_DECELEM)
             jsop_eleminc(op, stubs::DecElem);
           END_CASE(JSOP_DECELEM)
 
+          BEGIN_CASE(JSOP_NAMEINC)
+            jsop_nameinc(op, stubs::NameInc, fullAtomIndex(PC));
+            break;
+          END_CASE(JSOP_NAMEINC)
+
           BEGIN_CASE(JSOP_GNAMEINC)
-            jsop_nameinc(op, stubs::GlobalNameInc, fullAtomIndex(PC));
+            jsop_gnameinc(op, stubs::GlobalNameInc, fullAtomIndex(PC));
           END_CASE(JSOP_GNAMEINC)
 
           BEGIN_CASE(JSOP_PROPINC)
             jsop_propinc(op, stubs::PropInc, fullAtomIndex(PC));
             break;
           END_CASE(JSOP_PROPINC)
 
           BEGIN_CASE(JSOP_ELEMINC)
             jsop_eleminc(op, stubs::ElemInc);
           END_CASE(JSOP_ELEMINC)
 
           BEGIN_CASE(JSOP_NAMEDEC)
             jsop_nameinc(op, stubs::NameDec, fullAtomIndex(PC));
+            break;
           END_CASE(JSOP_NAMEDEC)
 
           BEGIN_CASE(JSOP_GNAMEDEC)
-            jsop_nameinc(op, stubs::GlobalNameDec, fullAtomIndex(PC));
+            jsop_gnameinc(op, stubs::GlobalNameDec, fullAtomIndex(PC));
           END_CASE(JSOP_GNAMEDEC)
 
           BEGIN_CASE(JSOP_PROPDEC)
             jsop_propinc(op, stubs::PropDec, fullAtomIndex(PC));
             break;
           END_CASE(JSOP_PROPDEC)
 
           BEGIN_CASE(JSOP_ELEMDEC)
@@ -2417,26 +2425,114 @@ mjit::Compiler::jsop_this()
         stubcc.linkExit(null, Uses(1));
         stubcc.leave();
         stubcc.call(stubs::This);
         stubcc.rejoin(Changes(1));
     }
 }
 
 void
-mjit::Compiler::jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index)
+mjit::Compiler::jsop_gnameinc(JSOp op, VoidStubAtom stub, uint32 index)
 {
     JSAtom *atom = script->getAtom(index);
     prepareStubCall(Uses(0));
     masm.move(ImmPtr(atom), Registers::ArgReg1);
     stubCall(stub);
     frame.pushSynced();
 }
 
 void
+mjit::Compiler::jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index)
+{
+    JSAtom *atom = script->getAtom(index);
+    jsbytecode *next = &PC[JSOP_NAMEINC_LENGTH];
+    bool pop = (JSOp(*next) == JSOP_POP) && !analysis[next].nincoming;
+    int amt = (op == JSOP_NAMEINC || op == JSOP_INCNAME) ? -1 : 1;
+
+#if ENABLE_PIC
+    if (pop || (op == JSOP_INCNAME || op == JSOP_DECNAME)) {
+        /* These cases are easy, the original value is not observed. */
+
+        jsop_name(atom);
+        // V
+
+        frame.push(Int32Value(amt));
+        // V 1
+
+        /* Use sub since it calls ValueToNumber instead of string concat. */
+        jsop_binary(JSOP_SUB, stubs::Sub);
+        // N+1
+
+        jsop_bindname(index);
+        // V+1 OBJ
+
+        frame.dup2();
+        // V+1 OBJ V+1 OBJ
+
+        frame.shift(-3);
+        // OBJ OBJ V+1
+
+        frame.shift(-1);
+        // OBJ V+1
+
+        jsop_setprop(atom);
+        // V+1
+
+        if (pop)
+            frame.pop();
+    } else {
+        /* The pre-value is observed, making this more tricky. */
+
+        jsop_name(atom);
+        // V
+
+        jsop_pos();
+        // N
+
+        frame.dup();
+        // N N
+
+        frame.push(Int32Value(-amt));
+        // N N 1
+
+        jsop_binary(JSOP_ADD, stubs::Add);
+        // N N+1
+
+        jsop_bindname(index);
+        // N N+1 OBJ
+
+        frame.dup2();
+        // N N+1 OBJ N+1 OBJ
+
+        frame.shift(-3);
+        // N OBJ OBJ N+1
+
+        frame.shift(-1);
+        // N OBJ N+1
+
+        jsop_setprop(atom);
+        // N N+1
+
+        frame.pop();
+        // N
+    }
+#else
+    prepareStubCall(Uses(1));
+    masm.move(ImmPtr(atom), Registers::ArgReg1);
+    stubCall(stub);
+    frame.pop();
+    frame.pushSynced();
+#endif
+
+    PC += JSOP_NAMEINC_LENGTH;
+    if (pop)
+        PC += JSOP_POP_LENGTH;
+}
+
+void
 mjit::Compiler::jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index)
 {
     JSAtom *atom = script->getAtom(index);
     jsbytecode *next = &PC[JSOP_PROPINC_LENGTH];
     bool pop = (JSOp(*next) == JSOP_POP) && !analysis[next].nincoming;
     int amt = (op == JSOP_PROPINC || op == JSOP_INCPROP) ? -1 : 1;
 
 #if ENABLE_PIC
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -198,16 +198,17 @@ class Compiler
     void jsop_setglobal(uint32 index);
     void jsop_getglobal(uint32 index);
     void jsop_getprop_slow();
     void jsop_getarg(uint32 index);
     void jsop_this();
     void emitReturn();
     void dispatchCall(VoidPtrStubUInt32 stub, uint32 argc);
     void inlineCallHelper(uint32 argc, bool callingNew);
+    void jsop_gnameinc(JSOp op, VoidStubAtom stub, uint32 index);
     void jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index);
     void jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index);
     void jsop_eleminc(JSOp op, VoidStub);
     void jsop_getgname(uint32 index);
     void jsop_getgname_slow(uint32 index);
     void jsop_setgname(uint32 index);
     void jsop_setgname_slow(uint32 index);
     void jsop_bindgname();
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -1332,16 +1332,20 @@ ic::SetProp(VMFrame &f, uint32 index)
     //
 
     VoidStubUInt32 stub;
     switch (JSOp(*f.regs.pc)) {
       case JSOP_PROPINC:
       case JSOP_PROPDEC:
       case JSOP_INCPROP:
       case JSOP_DECPROP:
+      case JSOP_NAMEINC:
+      case JSOP_NAMEDEC:
+      case JSOP_INCNAME:
+      case JSOP_DECNAME:
         stub = SetPropDumb;
         break;
       default:
         stub = SetPropSlow;
         break;
     }
 
     SetPropCompiler cc(f, script, obj, pic, atom, stub);